有没有可能让Python使用执行的主线程启动pyqt5gui应用程序,然后让线程打开来做其他事情?在
下面是我能想到的最简单的例子:
from PyQt5.QtWidgets import *
def infinite_useless_loop():
while True:
pass
app = QApplication([])
doodad = QMainWindow()
doodad.show()
infinite_useless_loop()
如果运行此代码,它将冻结,因为“mainloop”没有像通常那样被激活,如果我没有调用无用的无限循环,而是调用app.exec_()
。对infinite_useless_loop
的调用是为了在GUI正常运行的情况下,替换用于执行其他有用工作的主线程。在
为了正确地做到这一点,我不得不设想一个单独的线程并使用它来运行GUI,同时用主线程启动该线程,然后从那里继续;如果将来需要,可以进行通信。在
我写了一些代码,使主事件循环在一个单独的线程中工作,但是我仍然不能与在另一个线程中创建的GUI对象完全交互。这段代码有效地解决了我的一半问题:
^{pr2}$此代码生成空白窗口,可以单击并正确调整大小(因为事件循环正在工作),但它自己。我是否必须恢复到信号和插槽来与对象通信,或者我可以以某种方式将GUI对象恢复到主线程中并从那里使用它的方法?在
我不想在GUI线程之外进行任何实际的GUI操作,只需调用我生成的GUI对象上的方法。整个GUI结构将由GUI对象生成。在
这个新代码现在使它能够与通信,但只能与原始信息位通信,而不能由一个线程访问另一个线程的GUI对象的方法。虽然很接近,但还是不是我想要的。调用GUI对象的方法必须通过队列传递原始信息,然后在另一端进行处理。然后必须调用exec()
函数。这是不可接受的。代码如下:
from PyQt5.QtWidgets import *
import multiprocessing
import threading
import sys
import time
import queue
class Application(QMainWindow):
def __init__(self, comms):
super(Application, self).__init__()
self.comms = comms
self.fetchingThread = threading.Thread(target=self.fetchingLoop)
self.labelOne = QLabel(self)
self.layout = QVBoxLayout()
self.layout.addWidget(self.labelOne)
self.setLayout(self.layout)
self.fetchingThread.start()
def fetchingLoop(self):
while True:
try:
obj = self.comms.get()
self.processItem(obj)
except queue.Empty:
pass
def processItem(self, item):
self.labelOne.setText(str(item))
print(self.labelOne.text())
class Launcher(multiprocessing.Process):
def __init__(self, Application):
super(Launcher, self).__init__()
self.comms = multiprocessing.Queue()
self.Application = Application
def get_comms(self):
return self.comms
def run(self):
app = QApplication([])
window = self.Application(self.comms)
window.show()
sys.exit(app.exec_())
def no_thread():
app = QApplication([])
window = Application(False)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
thread = Launcher(Application)
comms = thread.get_comms()
thread.start()
c = 0
while True:
c += 1
time.sleep(1)
comms.put(c)
目前没有回答
相关问题 更多 >
编程相关推荐