<p>我们应该首先看看信号/槽如何只在一个Python进程中工作:</p>
<p>如果只有一个正在运行的QThread,它们就直接调用插槽。</p>
<p>如果信号是在另一个线程上发出的,它必须找到信号的目标线程,并在该线程的线程队列中放置一条消息/发送一个事件。该线程将在适当的时候处理消息/事件并调用信号。</p>
<p>所以,总是有某种内部的轮询,重要的是轮询是非阻塞的。</p>
<p>由<a href="https://docs.python.org/3.4/library/multiprocessing.html" rel="nofollow">multiprocessing</a>创建的进程可以通过管道进行通信,管道为每侧提供两个<a href="https://docs.python.org/3.4/library/multiprocessing.html#multiprocessing.Connection" rel="nofollow">connections</a>。</p>
<p><code>Connection</code>的<code>poll</code>函数是非阻塞的,因此我会定期用<code>QTimer</code>轮询它,然后相应地发出信号。</p>
<p>另一种解决方案可能是让线程模块(或QThread)中的<code>Thread</code>特别是使用队列的<code>get</code>函数等待来自<code>Queue</code>的新消息。有关详细信息,请参阅<a href="https://docs.python.org/2/library/multiprocessing.html#pipes-and-queues" rel="nofollow">multiprocessing</a>的管道和队列部分。。</p>
<p>下面是一个在另一个<code>Process</code>中启动Qt GUI的示例,同时还有一个<code>Thread</code>负责监听<code>Connection</code>和特定消息,关闭GUI,然后终止进程。</p>
<pre><code>from multiprocessing import Process, Pipe
from threading import Thread
import time
from PySide import QtGui
class MyProcess(Process):
def __init__(self, child_conn):
super().__init__()
self.child_conn = child_conn
def run(self):
# start a qt application
app = QtGui.QApplication([])
window = QtGui.QWidget()
layout = QtGui.QVBoxLayout(window)
button = QtGui.QPushButton('Test')
button.clicked.connect(self.print_something)
layout.addWidget(button)
window.show()
# start thread which listens on the child_connection
t = Thread(target=self.listen, args = (app,))
t.start()
app.exec_() # this will block this process until somebody calls app.quit
def listen(self, app):
while True:
message = self.child_conn.recv()
if message == 'stop now':
app.quit()
return
def print_something(self):
print("button pressed")
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
s = MyProcess(child_conn)
s.start()
time.sleep(5)
parent_conn.send('stop now')
s.join()
</code></pre>