【问题标题】:Drag and Drop QLabels with PyQt5使用 PyQt5 拖放 QLabels
【发布时间】:2018-10-18 08:21:07
【问题描述】:

我正在尝试使用 PyQt5 将 Qlabel 拖放到另一个 Qlabel 上:

from PyQt5.QtWidgets import QApplication, QWidget, QToolTip, QPushButton, QMessageBox, QHBoxLayout, QVBoxLayout, QGridLayout,QFrame, QComboBox, QLabel, QLineEdit
from PyQt5.QtGui import QIcon, QFont, QPixmap, QImage
import sys


class my_label(QLabel):
    def __init__(self,title,parent):
        super().__init__(title,parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self,event):
        if event.mimeData().hasFormat("text/plain"):
            event.accept()
        else:
            event.ignore()
    def dropEvent(self,event):
        self.setText(event.mimeData().text())


class application(QWidget):

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

    def initUI(self):


        label = my_label("drop there",self)
        label.resize(100,100)
        label.move(190,65)

        label_to_drag = QLabel("drag this",self)
        #label_to_drag.setDragEnabled(True)    #doesn't work with QLabel        
        self.show()


    def closeEvent(self,event):
        message = QMessageBox.question(self,"Message","Quit ?",QMessageBox.Yes | QMessageBox.No,QMessageBox.No)

        if message == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

app = QApplication(sys.argv)
fenetre = application()
sys.exit(app.exec_())

我想让我的第一个标签“可拖动”,通过调用setDragEnabled(True) 方法(就像我为 QLineEdit 所做的那样),并将它放在第二个标签上以更改他的文本。从另一个应用程序删除文本工作正常,但我找不到如何在我自己的应用程序中拖动 QLabel ... 我错过了什么 ?

编辑:修改代码以尝试拖放图像:

class DraggableLabel(QLabel):
def __init__(self,parent,image):
    super(QLabel,self).__init__(parent)
    self.setPixmap(QPixmap(image))    
    self.show()
def mousePressEvent(self, event):
    if event.button() == Qt.LeftButton:
        self.drag_start_position = event.pos()

def mouseMoveEvent(self, event):
    if not (event.buttons() & Qt.LeftButton):
        return
    if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
        return
    drag = QDrag(self)
    mimedata = QMimeData()
    mimedata.setText(self.text())

    drag.setMimeData(mimedata)
    pixmap = QPixmap(self.size())
    painter = QPainter(pixmap)
    painter.drawPixmap(self.rect(), self.grab())
    painter.end()
    drag.setPixmap(pixmap)
    drag.setHotSpot(event.pos())
    drag.exec_(Qt.CopyAction | Qt.MoveAction)

   class my_label(QLabel):
    def __init__(self,title,parent):
        super().__init__(title,parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self,event):
        if event.mimeData().hasFormat("text/plain"):
            print("event accepted")
            event.accept()
        else:
            print("event rejected")
            event.ignore()
    def dropEvent(self,event):
        if event.mimeData().hasImage():
            self.setPixmap(QPixmap.fromImage(QImage(event.mimeData().imageData())))

class application(QWidget):

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

    def initUI(self):

        label_to_drag = DraggableLabel(self,"index.jpg")

        label = my_label("drop there",self)
        label.resize(100,100)
        label.move(190,65)



        self.show()

当我将DraggableLabel(显示图像)放在my_label 上时,该事件被接受,但hasImage() 总是返回false...是我设置图像的方式错误吗?

【问题讨论】:

    标签: python python-3.x drag-and-drop pyqt pyqt5


    【解决方案1】:

    对于QLabel,您必须从头开始创建所有内容,为此您可以遵循docs 的示例。

    在下面的示例中,我放置了一个示例,其中一个类只接受拖放,另一个类只接受拖动,以便您可以看到每个部分并更好地理解。

    import sys
    
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget
    from PyQt5.QtGui import QDrag, QPixmap, QPainter, QCursor
    from PyQt5.QtCore import QMimeData, Qt
    
    
    class DraggableLabel(QLabel):
        def mousePressEvent(self, event):
            if event.button() == Qt.LeftButton:
                self.drag_start_position = event.pos()
    
        def mouseMoveEvent(self, event):
            if not (event.buttons() & Qt.LeftButton):
                return
            if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
                return
            drag = QDrag(self)
            mimedata = QMimeData()
            mimedata.setText(self.text())
            drag.setMimeData(mimedata)
            pixmap = QPixmap(self.size())
            painter = QPainter(pixmap)
            painter.drawPixmap(self.rect(), self.grab())
            painter.end()
            drag.setPixmap(pixmap)
            drag.setHotSpot(event.pos())
            drag.exec_(Qt.CopyAction | Qt.MoveAction)
    
    class DropLabel(QLabel):
        def __init__(self, *args, **kwargs):
            QLabel.__init__(self, *args, **kwargs)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, event):
            if event.mimeData().hasText():
                event.acceptProposedAction()
    
        def dropEvent(self, event):
            pos = event.pos()
            text = event.mimeData().text()
            self.setText(text)
            event.acceptProposedAction()
    
    
    class Widget(QWidget):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            label = DropLabel("drop there",self)
            label.setGeometry(190, 65, 100,100)
    
            label_to_drag = DraggableLabel("drag this",self)  
            self.show()
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = Widget()
        w.show()
        sys.exit(app.exec_())
    

    更新:

    不要将QDragQMimeData混淆,如果你想使用imageData()你必须将它设置为setImageData(),如docs所示:

    class DraggableLabel(QLabel):
        def __init__(self,parent,image):
            super(QLabel,self).__init__(parent)
            self.setPixmap(QPixmap(image))    
            self.show()
        def mousePressEvent(self, event):
            if event.button() == Qt.LeftButton:
                self.drag_start_position = event.pos()
    
        def mouseMoveEvent(self, event):
            if not (event.buttons() & Qt.LeftButton):
                return
            if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
                return
            drag = QDrag(self)
            mimedata = QMimeData()
            mimedata.setText(self.text())
            mimedata.setImageData(self.pixmap().toImage())
    
            drag.setMimeData(mimedata)
            pixmap = QPixmap(self.size())
            painter = QPainter(pixmap)
            painter.drawPixmap(self.rect(), self.grab())
            painter.end()
            drag.setPixmap(pixmap)
            drag.setHotSpot(event.pos())
            drag.exec_(Qt.CopyAction | Qt.MoveAction)
    
    class my_label(QLabel):
        def __init__(self,title,parent):
            super().__init__(title,parent)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self,event):
            if event.mimeData().hasImage():
                print("event accepted")
                event.accept()
            else:
                print("event rejected")
                event.ignore()
        def dropEvent(self,event):
            if event.mimeData().hasImage():
                self.setPixmap(QPixmap.fromImage(QImage(event.mimeData().imageData())))
    

    【讨论】:

    • 谢谢!我还有一个问题:我尝试使用setPixmap() 显示图像,然后将此图像拖到另一个标签上,并使此标签显示与第一个相同的图像,但它不起作用(见编辑)跨度>
    • @EinderJam QLabel 不显示文本或显示 QPixmap,不能同时显示。哪个版本?如果我的回答对您有帮助,别忘了标记为正确,如果您不知道怎么做,请查看tour,这是最好的感谢方式。
    • 非常有帮助的答案。谢谢+1
    猜你喜欢
    • 1970-01-01
    • 2017-05-27
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    相关资源
    最近更新 更多