gpt4 book ai didi

python - 如何从不同进程向 GUI 中的插槽发送信号?

转载 作者:太空狗 更新时间:2023-10-29 16:56:01 30 4
gpt4 key购买 nike

上下文:在 Python 中,主线程生成第二个进程(使用多处理模块),然后启动 GUI(使用 PyQt4)。此时主线程阻塞,直到 GUI 关闭。第二个进程始终在处理,理想情况下应该以异步方式向 GUI 中的特定插槽发出信号。

问题:Python 和 PyQt4 中有哪些方法/工具可用于实现该目标以及如何实现?最好以软中断方式而不是轮询方式。

抽象地说,我能想到的解决方案是在主线程中实例化一个“工具/处理程序”,它从 GUI 实例中获取可用的插槽,并与从第二个进程中获取的信号连接,假设我提供了这个工具一些预期或硬编码的信息。这可以实例化为第三个进程/线程。

最佳答案

这是一个 Qt 应用程序示例,演示了从子进程向母进程中的槽发送信号。我不确定这是正确的方法,但它确实有效。

我将进程区分为motherchild,因为 parent 这个词已经在 Qt 上下文中使用了。
母进程有两个线程。母进程主线程通过multiprocessing.Queue向子进程发送数据。子进程通过multiprocessing.Pipe将处理后的数据和待发送信号的签名发送给母进程的第二个线程。母进程的第二个线程实际上发出了信号。

Python 2.X、PyQt4:

from multiprocessing import Process, Queue, Pipe
from threading import Thread
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Emitter(QObject, Thread):

def __init__(self, transport, parent=None):
QObject.__init__(self,parent)
Thread.__init__(self)
self.transport = transport

def _emit(self, signature, args=None):
if args:
self.emit(SIGNAL(signature), args)
else:
self.emit(SIGNAL(signature))

def run(self):
while True:
try:
signature = self.transport.recv()
except EOFError:
break
else:
self._emit(*signature)

class Form(QDialog):

def __init__(self, queue, emitter, parent=None):
super(Form,self).__init__(parent)
self.data_to_child = queue
self.emitter = emitter
self.emitter.daemon = True
self.emitter.start()
self.browser = QTextBrowser()
self.lineedit = QLineEdit('Type text and press <Enter>')
self.lineedit.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.setWindowTitle('Upper')
self.connect(self.lineedit,SIGNAL('returnPressed()'),self.to_child)
self.connect(self.emitter,SIGNAL('data(PyQt_PyObject)'), self.updateUI)

def to_child(self):
self.data_to_child.put(unicode(self.lineedit.text()))
self.lineedit.clear()

def updateUI(self, text):
text = text[0]
self.browser.append(text)

class ChildProc(Process):

def __init__(self, transport, queue, daemon=True):
Process.__init__(self)
self.daemon = daemon
self.transport = transport
self.data_from_mother = queue

def emit_to_mother(self, signature, args=None):
signature = (signature, )
if args:
signature += (args, )
self.transport.send(signature)

def run(self):
while True:
text = self.data_from_mother.get()
self.emit_to_mother('data(PyQt_PyObject)', (text.upper(),))

if __name__ == '__main__':

app = QApplication(sys.argv)
mother_pipe, child_pipe = Pipe()
queue = Queue()
emitter = Emitter(mother_pipe)
form = Form(queue, emitter)
ChildProc(child_pipe, queue).start()
form.show()
app.exec_()

为了方便起见,还有 Python 3.X、PySide:

from multiprocessing import Process, Queue, Pipe
from threading import Thread

from PySide import QtGui, QtCore

class Emitter(QtCore.QObject, Thread):

def __init__(self, transport, parent=None):
QtCore.QObject.__init__(self, parent)
Thread.__init__(self)
self.transport = transport

def _emit(self, signature, args=None):
if args:
self.emit(QtCore.SIGNAL(signature), args)
else:
self.emit(QtCore.SIGNAL(signature))

def run(self):
while True:
try:
signature = self.transport.recv()
except EOFError:
break
else:
self._emit(*signature)

class Form(QtGui.QDialog):

def __init__(self, queue, emitter, parent=None):
super().__init__(parent)
self.data_to_child = queue
self.emitter = emitter
self.emitter.daemon = True
self.emitter.start()
self.browser = QtGui.QTextBrowser()
self.lineedit = QtGui.QLineEdit('Type text and press <Enter>')
self.lineedit.selectAll()
layout = QtGui.QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.lineedit)
self.setLayout(layout)
self.lineedit.setFocus()
self.setWindowTitle('Upper')
self.lineedit.returnPressed.connect(self.to_child)
self.connect(self.emitter, QtCore.SIGNAL('data(PyObject)'), self.updateUI)

def to_child(self):
self.data_to_child.put(self.lineedit.text())
self.lineedit.clear()

def updateUI(self, text):
self.browser.append(text[0])

class ChildProc(Process):

def __init__(self, transport, queue, daemon=True):
Process.__init__(self)
self.daemon = daemon
self.transport = transport
self.data_from_mother = queue

def emit_to_mother(self, signature, args=None):
signature = (signature, )
if args:
signature += (args, )
self.transport.send(signature)

def run(self):
while True:
text = self.data_from_mother.get()
self.emit_to_mother('data(PyQt_PyObject)', (text.upper(),))

if __name__ == '__main__':

app = QApplication(sys.argv)
mother_pipe, child_pipe = Pipe()
queue = Queue()
emitter = Emitter(mother_pipe)
form = Form(queue, emitter)
ChildProc(child_pipe, queue).start()
form.show()
app.exec_()

关于python - 如何从不同进程向 GUI 中的插槽发送信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26746379/

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