This article is part of the Qt Lab-CSDN blog series
The drag-and-drop operation includes two actions: drag and drop.
Drag allowed
For the window or control to be dragged out, setDragEnabled(true)
For the window or control to be dragged in, setAcceptDrops(true)
The following is a specific use case to illustrate
Drag items in the list control
This use case implements dragging from the list window on the left and dragging into the Widget window on the right.
Main interface settings
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { this->resize(1200,800); //Drag from ProjectListWidget to MyWidget QSplitter* center=new QSplitter; center->addWidget(new ProjectListWidget); center->addWidget(new MyWidget); center->setOrientation(Qt::Horizontal); this->setCentralWidget(center); }
Left list window settings
class ProjectListWidget : public QListWidget { Q_OBJECT public: ProjectListWidget(); // QAbstractItemView interface protected: void startDrag(Qt::DropActions supportedActions); };
The left window allows dragging its item, and the text in the item is stored in QMimeData for transfer to the right form.
ProjectListWidget::ProjectListWidget() { this->addItem("item1"); this->addItem("item2"); //(1) Enable dragging. If it is not enabled, there will be no effect of dragging the item. this->setDragEnabled(true); } //(2) Start dragging and set a drag data marked x1 void ProjectListWidget::startDrag(Qt::DropActions supportedActions) { QString text=this->currentItem()->text(); QMimeData* mimeData=new QMimeData; mimeData->setData("x1",text.toLocal8Bit()); QDrag* drag=new QDrag(this); drag->setMimeData(mimeData); drag->exec(); }
The form on the right has more implementations. First, the drag entry event dragEnterEvent must be allowed, and then the drag move event dragMoveEvent must be allowed. Finally, implement dropEvent to receive data.
MyWidget::MyWidget(QWidget *parent) : QWidget{parent} { //(1) Enable placement. If not enabled, a prohibition symbol will be displayed when dragging into the interface. this->setAcceptDrops(true); } //(2) After implementing the following two methods, the interface can allow drag and drop entry. //Allow drag-and-drop entry for a type of drag data marked x1 void MyWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("x1")) event->accept(); else event->ignore(); } void MyWidget::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("x1")) event->accept(); else event->ignore(); } //(3) Implement dropEvent to receive the data carried by dragging void MyWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasFormat("x1")) { QString text(event->mimeData()->data("x1")); QPoint pos=event->pos(); //Put the dragged data into the list here, and then draw it through paintEvent() m_textList.append({text,pos}); event->accept(); this->update(); } else event->ignore(); } void MyWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); for(int i=0;i<m_textList.size();i + + ) { QPoint pos=m_textList.at(i).second; QString text=m_textList.at(i).first; painter.drawText(pos,text); } }
The final effect is as follows
Event emission sequence and delivery rules
The above picture is referenced from Qt Drag and Drop (1): Basic Principles of Drag and Drop (QDrag Class) – CSDN Blog
About QDrag.exec()
void ProjectListWidget::startDrag(Qt::DropActions supportedActions) { //When calling this method, click on the item and move the mouse to enter the method //Then execute until drag->exec() blocks //The exec() function is a blocking function (but it will not block the main event loop) //In other words, "after drag" will not be printed before releasing the mouse. //But the window can still get other event responses. For example, mainwindow can still respond to update() triggered by QTimer. QString text=this->currentItem()->text(); QMimeData* mimeData=new QMimeData; mimeData->setData("x1",text.toLocal8Bit()); QDrag* drag=new QDrag(this); drag->setMimeData(mimeData); qDebug()<<"before drag"; drag->exec(); qDebug()<<"after drag"; }
Add the following code when constructing MainWindow:
QTimer* timer=new QTimer(this); timer->setInterval(1000); connect(timer, & amp;QTimer::timeout,[=]{ qDebug()<<"update..."; this->update(); }); timer->start();
Test whether the main window can respond to other events when the mouse is not released during dragging (yes)
bool MainWindow::event(QEvent *event) { qDebug()<<"event::"<<event; return QMainWindow::event(event); }
Drag the content in the Widget to another window or control
In the above example, the time to start dragging is within the startDrag() method. QListWidget::startDrag() can be rewritten, but for ordinary QWidgets, this method is not available
This example uses a LeftWidget inherited from QWidget as an example. Usually enable dragging in mousePressEvent()
void LeftWidget::mousePressEvent(QMouseEvent *event) { if(event->button()==Qt::LeftButton) { QString text="xxxxxxx"; QMimeData* mimeData=new QMimeData; mimeData->setData("x1",text.toLocal8Bit()); QDrag* drag=new QDrag(this); drag->setMimeData(mimeData); qDebug()<<"before drag"; drag->exec(); qDebug()<<"after drag"; } }
Continue to use MainWindow and MyWidget from the previous example to achieve the effect of dragging from LeftWidget to MyWidget
If you want to drag a button to another interface and move its text to another window
You can do this by inheriting QPushButton and then overriding its mousePressEvent, almost the same as overriding LeftWidget::mousePressEvent.
void MyButton::mousePressEvent(QMouseEvent *event) { if(event->button()==Qt::LeftButton) { QString text=this->text(); QMimeData* mimeData=new QMimeData; mimeData->setData("x1",text.toLocal8Bit()); QDrag* drag=new QDrag(this); drag->setMimeData(mimeData); qDebug()<<"before drag"; drag->exec(); qDebug()<<"after drag"; } return QPushButton::mousePressEvent(event); }
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. MySQL entry-level skills treeDatabase compositionTable 78128 people are learning the system