如何将小部件连接到在一个类中声明的自定义信号,同时在另一个类中
Posted
技术标签:
【中文标题】如何将小部件连接到在一个类中声明的自定义信号,同时在另一个类中【英文标题】:How to connect widget to custom signal declared in one class while being inside of another class 【发布时间】:2014-07-28 01:58:39 【问题描述】:简短说明:
声明了两个线程以及七个队列项。对于每个队列项,都创建了 QProgressBar,并使用队列的 setValue()
方法将它的一个实例分配给每个队列项。在 Thread 的 run()
方法内部,使用队列项的 get()
方法检索 QProgressBar 实例。虽然仍在run()
方法内部,但QProgressBar 实例连接到自定义“updateBar”信号,因此可以从正在运行的run()
方法(或任何其他线程的方法)内部更新进度条小部件。虽然代码似乎运行良好,但如果我在 MyWindow 类之外(与信号的连接是在 Thread 类内部进行的)将 QProgressBar 实例连接到 Signal 时做正确的事情,我想得到你的意见。我实施的方法是否有任何复杂性。还是我应该使用其他东西?
from PyQt4 import QtCore, QtGui
import Queue as queue
class PbWidget(QtGui.QProgressBar):
def __init__(self, parent=None):
super(PbWidget, self).__init__()
self.setMinimum(1)
self.setMaximum(100)
self._active = False
def update_bar(self, argValue):
self.setValue(argValue)
QtGui.qApp.processEvents()
def closeEvent(self, event):
self._active = False
class MyThread(QtCore.QThread):
def __init__(self, queue, parent=None):
QtCore.QThread.__init__(self, parent)
self.queue = queue
def run(self):
while True:
pb = self.queue.get()
pb.connect(self, QtCore.SIGNAL("updateBar"), pb.update_bar)
for i in range(0,11):
self.emit(QtCore.SIGNAL("updateBar"), i*10)
self.sleep(1)
self.queue.task_done()
pb.disconnect(self, QtCore.SIGNAL("updateBar"), pb.update_bar)
class MyWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.queue = queue.Queue()
cWidget = QtGui.QWidget(self)
self.setCentralWidget(cWidget)
self.layout = QtGui.QVBoxLayout(cWidget)
button=QtGui.QPushButton("Sumbit Threads")
button.clicked.connect(self.submitThreads)
self.layout.addWidget(button)
def submitThreads(self):
self.threads = []
for i in range(1, 3):
thread = MyThread(self.queue)
self.threads.append(thread)
thread.start()
numbers=[1,2,3,4,5,6,7]
for number in numbers:
pb=PbWidget()
self.layout.addWidget(pb)
self.queue.put(pb)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
window = MyWindow()
window.resize(300, 30)
window.show()
sys.exit(app.exec_())
【问题讨论】:
【参考方案1】:既然你有这个运行,我不明白你为什么要改变。
就个人而言,我不会在线程之间传递对象(即进度小部件),因为这不会扩展到多处理、集群等,并且无法从不同线程获取/设置相同的变量同时。
我使用的替代方法是传递简单的状态消息,并在主线程中有一个 QTimer 定期检查传入队列(使用 get_nowait() ),并适当地设置接口。
例如,在 GUI init 上设置一个计时器:
self.timer = QTimer(self)
self.timer.timeout.connect(self.timeout)
self.timer.start(100)
并在超时方法中:
coming = self.incoming.get_nowait()
其中incoming
是其他线程/进程可以写入的队列。在您的情况下,数据将包含进度条标识符和进度值。当没有数据等待时,get_nowait 将引发空异常。
有趣的是,如果您直接调用 pb.update_bar() 而不是使用信号机制会发生什么?
【讨论】:
'pb.update_bar()` 导致了我从未见过的 Q 抱怨不规则崩溃。快速谷歌搜索和第一个建议是不要尝试直接从线程的run()
方法设置进度条小部件。请发布一些关于如何在这种情况下使用get_nowait()
的示例。知道这很有趣。以上是关于如何将小部件连接到在一个类中声明的自定义信号,同时在另一个类中的主要内容,如果未能解决你的问题,请参考以下文章