QPixmap 和 GUI 线程
QPixmap and GUI threading
我正在尝试制作一个小示例,运行 一个线程正在执行屏幕截图并将其发送到要显示的 GUI 应用程序。但我得到这个 "error"
QPixmap: It is not safe to use pixmaps outside the GUI thread
我已经尝试阅读,但很难理解为什么它会给我这个,因为 QImage 是在主应用程序和 GUI 线程中创建的?
我希望我的标签显示线程捕获的图像。
class Main(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 280, 600)
self.layout = QtGui.QVBoxLayout(self)
self.testButton = QtGui.QPushButton("Click Me")
self.connect(self.testButton, QtCore.SIGNAL("clicked()"), self.Capture)
self.layout.addWidget(self.testButton)
self.label_ = QLabel(self)
self.label_.move(280, 120)
self.label_.resize(640, 480)
self.layout.addWidget(self.label_)
@pyqtSlot(QImage)
def ChangeFrame(self, image):
qimg = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
self.label_.setPixmap(QPixmap.fromImage(qimg))
def Capture(self):
self.thread_ = CaptureScreen()
self.connect(self.thread_, QtCore.SIGNAL("ChangeFrame(PyQt_PyObject)"), self.ChangeFrame, Qt.DirectConnection)
self.thread_.start()
class CaptureScreen(QtCore.QThread):
pixmap = pyqtSignal(QImage)
def __del__(self):
self.exiting = True
self.wait()
def run(self):
img = ImageGrab.grab(bbox=(100,10,400,780))
img_np = np.array(img)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
self.emit( QtCore.SIGNAL("ChangeFrame(PyQt_PyObject)"), frame)
app = QtGui.QApplication(sys.argv)
test = Main()
test.show()
app.exec_()
来自the docs:
Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
通过在连接信号时指定 Qt.DirectConnection
,您会导致 CaptureScreen
线程调用连接的方法,这意味着您正在 GUI 线程之外创建 QPixmap。
将连接类型更改为 Qt.QueuedConnection
是否可以解决问题?
我正在尝试制作一个小示例,运行 一个线程正在执行屏幕截图并将其发送到要显示的 GUI 应用程序。但我得到这个 "error"
QPixmap: It is not safe to use pixmaps outside the GUI thread
我已经尝试阅读,但很难理解为什么它会给我这个,因为 QImage 是在主应用程序和 GUI 线程中创建的?
我希望我的标签显示线程捕获的图像。
class Main(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 280, 600)
self.layout = QtGui.QVBoxLayout(self)
self.testButton = QtGui.QPushButton("Click Me")
self.connect(self.testButton, QtCore.SIGNAL("clicked()"), self.Capture)
self.layout.addWidget(self.testButton)
self.label_ = QLabel(self)
self.label_.move(280, 120)
self.label_.resize(640, 480)
self.layout.addWidget(self.label_)
@pyqtSlot(QImage)
def ChangeFrame(self, image):
qimg = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
self.label_.setPixmap(QPixmap.fromImage(qimg))
def Capture(self):
self.thread_ = CaptureScreen()
self.connect(self.thread_, QtCore.SIGNAL("ChangeFrame(PyQt_PyObject)"), self.ChangeFrame, Qt.DirectConnection)
self.thread_.start()
class CaptureScreen(QtCore.QThread):
pixmap = pyqtSignal(QImage)
def __del__(self):
self.exiting = True
self.wait()
def run(self):
img = ImageGrab.grab(bbox=(100,10,400,780))
img_np = np.array(img)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
self.emit( QtCore.SIGNAL("ChangeFrame(PyQt_PyObject)"), frame)
app = QtGui.QApplication(sys.argv)
test = Main()
test.show()
app.exec_()
来自the docs:
Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
通过在连接信号时指定 Qt.DirectConnection
,您会导致 CaptureScreen
线程调用连接的方法,这意味着您正在 GUI 线程之外创建 QPixmap。
将连接类型更改为 Qt.QueuedConnection
是否可以解决问题?