David Basalla
David Basalla

Reputation: 3106

How to drag and drop into a QTableWidget? (PyQT)

I'm struggling with getting drag&drop to work. I want to be able to drag&drop from a QPushButton into a cell of a QTableView. I've looked at a few tutorials online but seem to be stuck at the first step. The example below is changed from the amazing zetcode tutorial: http://zetcode.com/tutorials/pyqt4/dragdrop/

Using the code below, when I drag the button into tableWidget, the dragEnterEvent seems to be get called, but once I hover the mouse over the table, I get that symbol that I'm not allowed to drop over the table, so can never get to the drop event :(

I have to admit I'm fairly new to pyqt, so may be missing something very simple. Would really appreciate any help I could get! Cheers Dave

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore


class Button(QtGui.QPushButton):

    def __init__(self, title, parent):
        super(Button, self).__init__(title, parent)


    def mouseMoveEvent(self, e):
        if e.buttons() != QtCore.Qt.RightButton:
            return

        mimeData = QtCore.QMimeData()
        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(e.pos() - self.rect().topLeft())

       dropAction = drag.start(QtCore.Qt.MoveAction)


    def mousePressEvent(self, e):

        QtGui.QPushButton.mousePressEvent(self, e)
        if e.button() == QtCore.Qt.LeftButton:
            print 'press'


class MyTable(QtGui.QTableWidget):

    def __init__(self, rows, columns, parent):
        super(MyTable, self).__init__(rows, columns, parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, e):
        print e.accept()

    def dropEvent(self, e):
        print 'blah'

        position = e.pos()
        self.button.move(position)

        e.setDropAction(QtCore.Qt.MoveAction)

        e.accept()



class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()
        self.initUI()

    def initUI(self):
        self.setAcceptDrops(True)
        self.button = Button('Button', self)

        self.table = MyTable(2,2,self)
        self.table.setAcceptDrops(True)
        self.table.setDragEnabled(True)

        self.setWindowTitle('Click or Move')

        self.setGeometry(300, 300, 280, 150)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.button)
        layout.addWidget(self.table)
        self.setLayout(layout)


def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    ex.show()
    app.exec_()  


if __name__ == '__main__':

    main()

Upvotes: 5

Views: 7915

Answers (1)

jdi
jdi

Reputation: 92657

Because you are setting up drag and drop on a QTableWidget, you also need to re-implement it's dragMoveEvent. As per the docs here:

Subclassing Complex Widgets
Certain standard Qt widgets provide their own support for drag and drop. When subclassing these widgets, it may be necessary to reimplement dragMoveEvent() in addition to dragEnterEvent() and dropEvent() to prevent the base class from providing default drag and drop handling, and to handle any special cases you are interested in.

class MyTable(QtGui.QTableWidget):
    ...
    def dragMoveEvent(self, e):
        e.accept()

Also, be aware that while the original tutorial shows how to move a button within a widget without any layouts, your example now has the button managed by a vertical layout. So your self.button.move(position) will not work as expected. Though the dropEvent should fire properly and you should be getting the "accepted" drag icon when it hovers a cell.

Upvotes: 7

Related Questions