gpt4 book ai didi

python - 无法从线程显示窗口

转载 作者:太空宇宙 更新时间:2023-11-03 18:36:22 25 4
gpt4 key购买 nike

我有几个线程需要使用 window.这是线程定义:

class MyThread(QtCore.QThread):
def __init__(self, id, window, mutex):
super(MyThread, self).__init__()
self.id = id
self.window = window
self.mutex = mutex
self.connect(self, QtCore.SIGNAL("load_message_input()"), self.window, QtCore.SLOT("show_input()"))

def run(self):
self.mutex.lock()
self.emit(QtCore.SIGNAL("load_message_input()"))
self.connect(self.window, QtCore.SIGNAL("got_message(QString)"), self.print_message)
self.window.input_finished.wait(self.mutex)
self.mutex.unlock()

def print_message(self, str):
print "Thread %d: %s" % (self.id, str)

这是窗口定义:

class MyDialog(QtGui.QDialog):
def __init__(self, *args, **kwargs):
super(MyDialog, self).__init__(*args, **kwargs)
self.last_message = None

self.setModal(True)
self.message_label = QtGui.QLabel(u"Message")
self.message_input = QtGui.QLineEdit()
self.dialog_buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
self.dialog_buttons.accepted.connect(self.accept)
self.dialog_buttons.rejected.connect(self.reject)
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.message_label)
self.hbox.addWidget(self.message_input)
self.vbox = QtGui.QVBoxLayout()
self.vbox.addLayout(self.hbox)
self.vbox.addWidget(self.dialog_buttons)
self.setLayout(self.vbox)

self.input_finished = QtCore.QWaitCondition()

@QtCore.pyqtSlot()
def show_input(self):
self.exec_()

def on_accepted(self):
self.emit(QtCore.SIGNAL("got_message(QString)"), self.message_input.text())
self.input_finished.wakeOne()

这是主要的:

if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)

mutex = QtCore.QMutex()
threads = []
window = test_qdialog.MyDialog()

for i in range(5):
thread = MyThread(i, window, mutex)
thread.start()
threads.append(thread)

for t in threads:
t.wait()

sys.exit(app.exec_())

我不明白为什么执行脚本时不显示窗口。

更新:由于某种原因,其他线程不会通过 self.mutex.lock() 在线停止。不明白为什么。

最佳答案

您的代码中有几个问题:

  • 如果您希望QThread使用插槽,您需要为其创建一个事件循环(这很简单,只需调用QThread.exec_),但是带有事件循环的 QThread 需要以不同的方式编码(接下来我将向您发布一个示例)
  • 如果您想发出消息,则需要将 on_accepted 连接到 accepted,除非您使用 Qt 的自动连接功能。
  • 如果您想首先使用QThread,您需要启动一个QApplication,因此for t inthreads: t.wait() 可以'不会在调用 QApplication.exec_ 之前执行(在我的示例中只是将其删除)。
  • 最后但同样重要的问题:如果您希望线程专门消耗资源,您应该考虑消费者-生产者方法(问题是,当您发出信号时,每个插槽都会获得数据的副本,并且如果您尝试使用事件循环阻塞线程,应用程序就会卡住,为了解决消费者-生产者的问题,我将一个额外的互斥体传递给消息的信号,并尝试锁定它[永远不会阻塞! ] 了解线程是否消费该事件)

正如所 promise 的,有一个如何在 QThread 上使用事件循环的示例:

from PyQt4 import QtCore, QtGui

class MyThread(QtCore.QThread):

load_message_input = QtCore.pyqtSignal()

def __init__(self, id, window):
super(MyThread, self).__init__()
self.id = id
self.window = window
self.load_message_input.connect(self.window.show_input)
self.window.got_message.connect(self.print_message)
self.started.connect(self.do_stuff)

def run(self):
print "Thread %d: %s" % (self.id,"running")
self.exec_()

@QtCore.pyqtSlot()
def do_stuff(self):
print "Thread %d: %s" % (self.id,"emit load_message_input")
self.load_message_input.emit()

@QtCore.pyqtSlot("QString","QMutex")
def print_message(self, msg, mutex):
if mutex.tryLock():
print "Thread %d: %s" % (self.id, msg)
self.do_stuff()


class MyDialog(QtGui.QDialog):

got_message = QtCore.pyqtSignal("QString","QMutex")

def __init__(self, *args, **kwargs):
super(MyDialog, self).__init__(*args, **kwargs)
self.last_message = None

self.setModal(True)
self.message_label = QtGui.QLabel(u"Message")
self.message_input = QtGui.QLineEdit()
self.dialog_buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
self.dialog_buttons.accepted.connect(self.accept)
self.dialog_buttons.accepted.connect(self.on_accepted)
self.dialog_buttons.rejected.connect(self.reject)
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.message_label)
self.hbox.addWidget(self.message_input)
self.vbox = QtGui.QVBoxLayout()
self.vbox.addLayout(self.hbox)
self.vbox.addWidget(self.dialog_buttons)
self.setLayout(self.vbox)

self.input_finished = QtCore.QWaitCondition()


@QtCore.pyqtSlot()
def show_input(self):
print "showing input"
window.show()
window.setModal(True)


@QtCore.pyqtSlot()
def on_accepted(self):
print "emit: ", self.message_input.text()
self.got_message.emit(self.message_input.text(), QtCore.QMutex())

if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)

mutex = QtCore.QMutex()
threads = []
window = MyDialog()

for i in range(5):
thread = MyThread(i, window)
thread.start()
threads.append(thread)

print "start app"
sys.exit(app.exec_())

注意:几乎总是第一个收到信号的线程是 id 1 的线程。

我的建议是,不要在线程中使用槽(这样可以安全地使用互斥体和等待条件)并为消息实现消费者-生产者方法。

关于python - 无法从线程显示窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21525703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com