c++ - 如何在 Qt 中将 QLabel 从一个窗口拖到另一个窗口?
问题描述
我学习 Qt 是为了好玩。我有一个问题:
我如何在两个不同的窗口之间拖放 Qt 中的 QLabel?
这是我到目前为止所拥有的:
正如您从上面提供的.gif
(由于某些原因不想被下载并在此处显示,但如果您单击它的链接,您可以清楚地看到它)可以看出,现在有两个主要问题:
我无法移动
QLabel
窗口的外部(因此无法注册拖放事件)。当我移动它时,标签由于某些原因闪烁。
以下是实现的相关部分.gif
:
#ifndef DRAGGERP_H
#define DRAGGERP_H
#include <QLabel>
#include <QApplication>
#include <QMouseEvent>
#include <QPoint>
class DraggerP : public QLabel
{
QPoint offset;
QPoint startingPosition;
public:
DraggerP(QWidget* parent = nullptr) : QLabel(parent){ }
protected:
void enterEvent(QEvent* event) override
{
QApplication::setOverrideCursor(Qt::PointingHandCursor);
}
void leaveEvent(QEvent* event) override
{
QApplication::restoreOverrideCursor();
}
void mousePressEvent(QMouseEvent* event) override
{
startingPosition = pos();
offset = QPoint(
event->pos().x() - pos().x() + 0.5*width(),
event->pos().y() - pos().y() + 0.5*height()
);
}
void mouseMoveEvent(QMouseEvent* event) override
{
move(event->pos() + offset);
}
void mouseReleaseEvent(QMouseEvent* event) override
{
move(startingPosition);
}
};
#endif // DRAGGERP_H
这是QLabel
我用来创建拖放效果的扩展。
我不需要整个解决方案,至少需要知道如何完成此任务以及我在这里做错了什么。
这是一个很好的例子,我用它作为起点。
解决方案
遭受这种奇怪的运动QLabel
是因为QLabel
现在的位置取决于布局,布局的工作是根据您建立的策略确定小部件的位置。
解决方案不是在 MainWindow 中QLabel
而是在 MainWindow 中实现这些操作,如下所示:
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QTime>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
class MainWindow: public QMainWindow {
QScrollArea scrollArea;
QWidget contentWidget;
QVBoxLayout lay;
public:
MainWindow(QWidget* parent=nullptr): QMainWindow(parent){
qsrand((uint) QTime::currentTime().msec());
setCentralWidget(&scrollArea);
scrollArea.setWidget(&contentWidget);
contentWidget.setLayout(&lay);
scrollArea.setWidgetResizable(true);
for(int i=0; i< 20; i++){
QLabel *label = new QLabel(QString("label %1").arg(i));
QPalette pal = label->palette();
pal.setColor(QPalette::Background, QColor(10 +qrand() % 240, 10 +qrand() % 240, 10 +qrand() % 240));
label->setAutoFillBackground(true);
label->setPalette(pal);
lay.addWidget(label);
}
setAcceptDrops(true);
}
protected:
void mousePressEvent(QMouseEvent *event){
QMainWindow::mousePressEvent(event);
QWidget *child = childAt(event->pos());
if(qobject_cast<QLabel *>(child))
createDrag(event->pos(), child);
}
void dropEvent(QDropEvent *event){
QByteArray byteArray = event->mimeData()->data("Label");
QWidget * widget = *reinterpret_cast<QWidget**>(byteArray.data());
QLabel * new_label = qobject_cast<QLabel *>(widget);
QWidget *current_children = childAt(event->pos());
QLabel * current_label = qobject_cast<QLabel*>(current_children);
int index = 0;
if(new_label){
if(current_label)
index = lay.indexOf(current_label);
else{
index = 0;
QLayoutItem *item = lay.itemAt(index);
while(item->widget()->pos().y() < event->pos().y() && item)
item = lay.itemAt(index++);
}
lay.insertWidget(index, new_label);
}
}
private:
void createDrag(const QPoint &pos, QWidget *widget){
if(widget == Q_NULLPTR)
return;
QByteArray byteArray(reinterpret_cast<char*>(&widget),sizeof(QWidget*));
QDrag *drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;
mimeData->setData("Label",byteArray);
drag->setMimeData(mimeData);
QPoint globalPos = mapToGlobal(pos);
QPoint p = widget->mapFromGlobal(globalPos);
drag->setHotSpot(p);
drag->setPixmap(widget->grab());
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
protected:
void dragEnterEvent(QDragEnterEvent *event){
if(event->mimeData()->hasFormat("Label"))
event->acceptProposedAction();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
MainWindow w2;
w1.show();
w2.show();
return a.exec();
}
推荐阅读
- java - How to choice what method should be called when use polymorphism
- google-custom-search - Google Custom Search API 使用哪个时区来计算每日配额?
- c++ - 在 64 位 Debian 上交叉编译 32 位时找不到 Libpcap
- ionic-framework - 我在离子应用程序中集成了 rtmp 流媒体,但视频没有播放
- java - nutch 1.13 中某些 https url 的 javax.net.ssl.SSLHandshakeException
- java - Implementing Authorization using keycloak, after extracting the RPT token how to map the Resource Name with the controllers and unauthorize a user
- javascript - 通过 ajax 附加 div,我在附加 div 后选择的类名是不工作的
- php - 在 url php 中添加 GET 参数
- grafana - 是否可以根据名称过滤使用 GRAFANA 在仪表板中创建的面板
- java - Java program to short and count