是否有可能让Python使用主要执行线程启动PyQt5 GUI应用程序,然后让线程处于打开状态以执行其他操作?
这是我能想到的最简单的例子:
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
的调用意味着用正在运行的其他有用工作 WHILE 替换正在运行的GUI。
为了正确地做到这一点,我不得不想象一个人会创建一个单独的线程并使用它来运行GUI,同时用主线程启动该线程,然后从那里继续;能够在将来必要时进行沟通。
我写了一些代码,让主事件循环在一个单独的线程中工作,但我仍然无法与另一个线程中创建的GUI对象完全交互。这段代码有效地解决了我的一半问题:
from PyQt5.QtWidgets import *
from threading import Thread
import sys
def makeGUI():
app = QApplication([])
doodad = QMainWindow()
doodad.show()
sys.exit(app.exec_())
def infinite_useless_loop():
while True:
pass
if __name__ == '__main__':
thread = Thread(target=makeGUI)
thread.start()
infinite_useless_loop()
此代码生成空白窗口,可以单击并正确调整大小(因为事件循环正在运行),但它是独立的。我是否必须恢复信号和插槽以与对象通信,或者我可以以某种方式将GUI对象重新放回主线程并使用它的方法吗?
我不希望在GUI的线程之外进行任何实际的GUI操作,只需在GUI对象上调用 I HAVE MADE 的方法。整个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)