我正在使用Windows,Python 3.6,OpenCV3和PyQt5。我有一个包含两个QLabel小部件(label1
和label2
)的主窗口。我想将不同的视频文件拖放到两个QLabel小部件中。我的脚本显示了两个视频文件的第一帧。
如果我将文件通过 label1
拖到label2
中,然后释放
鼠标,则第一个视频帧显示在label1
中(不是
我想要)。
如果我将文件{em> 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_())
答案 0 :(得分:0)
文档表明underMouse()
在拖放过程中可能会失败:
布尔QWidget :: underMouse()常量
如果小部件位于鼠标光标下方,则返回true;否则,返回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_())