【问题标题】:PyQt - Drag and Drop into Different QLabel WidgetsPyQt - 拖放到不同的 QLabel 小部件中
【发布时间】:2019-05-07 11:21:06
【问题描述】:

我正在使用 Windows、Python 3.6、OpenCV3 和 PyQt5。我有一个包含两个 QLabel 小部件(label1label2)的主窗口。我想将不同的视频文件拖放到两个 QLabel 小部件中。我的脚本显示两个视频文件中的每一个的第一帧。

  • 如果我将一个文件 通过 label1 拖入 label2 然后释放 鼠标,那么第一个视频帧显示在label1(不是什么 我想要)。

  • 如果我将一个文件 环绕 label1 拖到 label2 中,然后释放 鼠标,则第一个视频帧显示在label2(需要 效果)。

  • 如果我将文件 通过 label2 拖入 label1 然后释放 鼠标,则第一个视频帧显示在label1(所需 效果)。

我想在label2 中显示视频,无论我是拖动文件环绕 还是穿过 label1。有什么建议吗?

import sys, cv2
from PyQt5.QtWidgets import QApplication, QLabel, QFrame, QMainWindow
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import Qt

class Example(QMainWindow):

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

    def initUI(self):

        self.setGeometry(200, 300, 800, 600)
        self.setAcceptDrops(True)
        self.setMouseTracking(True)

        self.label1 = QLabel(self)
        self.label1.move(10, 10)
        self.label1.resize(780, 280)
        self.label1.setFrameShape(QFrame.Box)
        self.label1.setAcceptDrops(True)

        self.label2 = QLabel(self)
        self.label2.move(10, 310)
        self.label2.resize(780, 280)
        self.label2.setFrameShape(QFrame.Box)
        self.label2.setAcceptDrops(True)

        self.label1.setText("Label 1")
        self.label2.setText("Label 2")
        self.show()

    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls:
            e.accept()
        else:
            e.ignore()

    def dropEvent(self, e):
        if e.mimeData().hasUrls:
            e.accept()
            for url in e.mimeData().urls():
                if self.label1.underMouse():
                    fname = str(url.toLocalFile())
                    self.openFile1(fname)
                elif self.label2.underMouse():
                    fname = str(url.toLocalFile())
                    self.openFile2(fname)
        else:
            e.ignore()

    def openFile1(self, filename):
        self.cap1 = cv2.VideoCapture(str(filename))
        self.cap1.set(cv2.CAP_PROP_POS_FRAMES, 0)
        width = self.cap1.get(cv2.CAP_PROP_FRAME_WIDTH)
        height = self.cap1.get(cv2.CAP_PROP_FRAME_HEIGHT)
        ret, frame = self.cap1.read()
        if ret == True:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
            pix = QPixmap.fromImage(img)
            pix = self.scalePix(self.label1, pix, width, height)
            self.label1.setPixmap(pix)

    def openFile2(self, filename):
        self.cap2 = cv2.VideoCapture(str(filename))
        self.cap2.set(cv2.CAP_PROP_POS_FRAMES, 0)
        width = self.cap2.get(cv2.CAP_PROP_FRAME_WIDTH)
        height = self.cap2.get(cv2.CAP_PROP_FRAME_HEIGHT)
        ret, frame = self.cap2.read()
        if ret == True:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
            pix = QPixmap.fromImage(img)
            pix = self.scalePix(self.label1, pix, width, height)
            self.label2.setPixmap(pix)

    def scalePix(self, label, p, width, height):
        window_width = label.width()
        ratio = height / width
        window_height = int(ratio * window_width)
        window_height = label.height() 
        window_width = int(1 / ratio * window_height)
        p = p.scaledToWidth(window_width, Qt.SmoothTransformation)
        p = p.scaledToHeight(window_height, Qt.SmoothTransformation)
        return p

if __name__ == '__main__':    
    app = QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python pyqt drag-and-drop pyqt5 qlabel


    【解决方案1】:

    文档表明underMouse()在拖放过程中可能会失败:

    bool QWidget::underMouse() const

    如果小部件在鼠标光标下,则返回 true;否则 返回 false。

    在拖放操作期间,此值未正确更新。

    所以最好不要使用,相反我们可以创建一个自定义的 QLabel 来实现拖放:

    import sys, cv2
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class OpenCVLabel(QtWidgets.QLabel):
        def __init__(self, *args, **kwargs):
            super(OpenCVLabel, self).__init__(*args, **kwargs)
            self.setFrameShape(QtWidgets.QFrame.Box)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, e):
            if e.mimeData().hasUrls():
                e.accept()
            else:
                e.ignore()
    
        def dropEvent(self, e):
            if e.mimeData().hasUrls():
                e.accept()
                for url in e.mimeData().urls():
                    self.openFile(url.toLocalFile())
            else:
                e.ignore()
    
        def openFile(self, filename):
            cap = cv2.VideoCapture(str(filename))
            cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
            width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
            height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
            ret, frame = cap.read()
            if ret:
                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
                pix = QtGui.QPixmap.fromImage(img)
                pix = pix.scaled(self.size(), QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
                self.setPixmap(pix)
    
    class Example(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            label1 = OpenCVLabel("label1")
            label2 = OpenCVLabel("label2")
            central_widget = QtWidgets.QWidget()
            self.setCentralWidget(central_widget)
            lay = QtWidgets.QVBoxLayout(central_widget)
            lay.addWidget(label1)
            lay.addWidget(label2)
            self.resize(780, 560)
    
    if __name__ == '__main__':    
        app = QtWidgets.QApplication(sys.argv)
        ex = Example()
        ex.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 完美!奇迹般有效!谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    • 2012-06-10
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    相关资源
    最近更新 更多