【问题标题】:PySide How to keep QLabel visible when I drag and drop?PySide 如何在拖放时保持 QLabel 可见?
【发布时间】:2019-12-05 23:36:44
【问题描述】:

我想拖放标签,我的代码就是这样做的,但是在移动它时标签消失了。如何在拖动标签时保持标签可见?我正在使用 QDrag 复制内容。

我希望能够将这些标签拖到一个有许多插槽的盒子中,并在标签掉到附近时将标签锁定到其中一个插槽中。由于标签在被拖动时变得不可见,因此当我松开鼠标按钮时,很难想象它会被放置在哪里。

from PySide import QtCore, QtGui

myMimeType = 'application/MyWindow'

class MyLabel(QtGui.QLabel):
    def __init__(self, parent):
        super(MyLabel, self).__init__(parent)

        self.setStyleSheet("""
            background-color: black;
            color: white;
            font: bold;
            padding: 6px;
            border-width: 2px;
            border-style: solid;
            border-radius: 16px;
            border-color: white;
        """)

    def mousePressEvent(self, event):
        itemData   = QtCore.QByteArray()
        dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
        dataStream.writeString(self.text())
        dataStream << QtCore.QPoint(event.pos() - self.rect().topLeft())
    print dataStream

        mimeData = QtCore.QMimeData()
        mimeData.setData(myMimeType, itemData)
        mimeData.setText(self.text())

        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(event.pos() - self.rect().topRight())

        self.hide()

        if drag.exec_(QtCore.Qt.MoveAction | QtCore.Qt.CopyAction, QtCore.Qt.CopyAction) == QtCore.Qt.MoveAction:
            self.close()

        else:
            self.show()


class MyFrame(QtGui.QFrame):
    def __init__(self, parent=None):
        super(MyFrame, self).__init__(parent)

        self.setStyleSheet("""
            background-color: lightgray;
            border-width: 2px;
            border-style: solid;
            border-color: black;
            margin: 2px;
        """)

        y = 6
        for labelNumber in range(6):
            label = MyLabel(self)
            label.setText("Label #{0}".format(labelNumber))
            label.move(6, y)
            label.show()

            y += label.height() + 2

        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat(myMimeType):
            if event.source() in self.children():
                event.setDropAction(QtCore.Qt.MoveAction)
                event.accept()

            else:
                event.acceptProposedAction()

        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasFormat(myMimeType):
            mime       = event.mimeData()
            itemData   = mime.data(myMimeType)
            dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)

            text = QtCore.QByteArray()
            offset = QtCore.QPoint()
            dataStream >> text >> offset

            newLabel = MyLabel(self)
            newLabel.setText(event.mimeData().text())
            newLabel.move(event.pos() - offset)
            newLabel.show()

            if event.source() in self.children():
                event.setDropAction(QtCore.Qt.MoveAction)
                event.accept()

            else:
                event.acceptProposedAction()

        else:
            event.ignore()

class MyWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)

        self.myFrame = MyFrame(self)

        self.setCentralWidget(self.myFrame)

if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    app.setApplicationName('MyWindow')

    main = MyWindow()
    main.resize(333, 333)
    main.move(app.desktop().screen().rect().center() - main.rect().center())
    main.show()

    sys.exit(app.exec_())

【问题讨论】:

    标签: python qt pyqt drag-and-drop pyside


    【解决方案1】:

    您必须保存小部件并将其设置在 QDrag 中:

    from PySide import QtCore, QtGui
    
    myMimeType = "application/MyWindow"
    
    
    class MyLabel(QtGui.QLabel):
        def __init__(self, parent):
            super(MyLabel, self).__init__(parent)
    
            self.setStyleSheet(
                """
                background-color: black;
                color: white;
                font: bold;
                padding: 6px;
                border-width: 2px;
                border-style: solid;
                border-radius: 16px;
                border-color: white;
            """
            )
    
        def mousePressEvent(self, event):
            itemData = QtCore.QByteArray()
            dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.WriteOnly)
            dataStream.writeString(self.text())
            dataStream << QtCore.QPoint(event.pos() - self.rect().topLeft())
    
            mimeData = QtCore.QMimeData()
            mimeData.setData(myMimeType, itemData)
            mimeData.setText(self.text())
    
            drag = QtGui.QDrag(self)
            drag.setMimeData(mimeData)
            drag.setHotSpot(event.pos())
            # pixmap = self.grab()
            pixmap = QtGui.QPixmap(self.size())
            self.render(pixmap)
            drag.setPixmap(pixmap)
            self.hide()
    
            action = drag.exec_(
                QtCore.Qt.MoveAction | QtCore.Qt.CopyAction, QtCore.Qt.CopyAction
            )
            if action == QtCore.Qt.MoveAction:
                self.deleteLater()
            else:
                self.show()
    
    
    class MyFrame(QtGui.QFrame):
        def __init__(self, parent=None):
            super(MyFrame, self).__init__(parent)
    
            self.setStyleSheet(
                """
                background-color: lightgray;
                border-width: 2px;
                border-style: solid;
                border-color: black;
                margin: 2px;
            """
            )
    
            y = 6
            for labelNumber in range(6):
                label = MyLabel(self)
                label.setText("Label #{0}".format(labelNumber))
                label.move(6, y)
                label.show()
    
                y += label.height() + 2
    
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, event):
            if event.mimeData().hasFormat(myMimeType):
                if event.source() in self.children():
                    event.acceptProposedAction()
    
        def dropEvent(self, event):
            if event.mimeData().hasFormat(myMimeType):
                if (
                    event.source() in self.children()
                    and event.possibleActions() & QtCore.Qt.MoveAction
                ):
                    event.acceptProposedAction()
                    mime = event.mimeData()
                    itemData = mime.data(myMimeType)
                    dataStream = QtCore.QDataStream(itemData, QtCore.QIODevice.ReadOnly)
    
                    text = QtCore.QByteArray()
                    offset = QtCore.QPoint()
                    dataStream >> text >> offset
    
                    newLabel = MyLabel(self)
                    newLabel.setText(event.mimeData().text())
                    newLabel.move(event.pos() - offset)
                    newLabel.show()
                    event.setDropAction(QtCore.Qt.MoveAction)
            else:
                event.ignore()
    
    
    class MyWindow(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent)
            self.myFrame = MyFrame()
            self.setCentralWidget(self.myFrame)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtGui.QApplication(sys.argv)
        app.setApplicationName("MyWindow")
        main = MyWindow()
        main.resize(333, 333)
        main.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 在 Win7x64 上使用 Pyside 和 Python 2.7.15,我得到了 AttributeError: 'MyLabel' object has no attribute 'grab'
    • @noEmbryo 我已经用 PySide2 对其进行了测试,但我看到在 Qt5 中引入了抓取。我刚刚用 Qt4 兼容代码替换了它,因此 PySide 兼容,请再试一次。
    • 谢谢,它有效!你能看一下这个问题,这个项目的下一步是什么? stackoverflow.com/questions/59218941/…
    猜你喜欢
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多