运行 不同线程中的进度条 - Pyside
Running progress bar in a different thread - Pyside
我想 运行 在与我的其余代码不同的线程中创建一个进度条,但我想控制进度条如何从我的主线程更新。
这是可能的吗?
这是我目前拥有的:
import time
from PySide import QtGui
from PySide import QtCore
from PySide import QtUiTools
class progressBar(QtGui.QDialog, QtCore.QThread):
def __init__(self, window, title=None):
super(progressBar, self).__init__(window)
QtCore.QThread.__init__(self)
self.title = title or 'Progress'
self.setupUi()
self.show()
def setupUi(self):
self.setObjectName("Thinking")
self.gridLayout = QtGui.QGridLayout(self)
self.gridLayout.setObjectName("gridLayout")
self.progressBar = QtGui.QProgressBar(self)
self.gridLayout.addWidget(self.progressBar, 0, 0, 1, 1)
# ADJUSTMENTS
self.setMaximumSize(280, 50)
self.setMinimumSize(280, 50)
self.setWindowTitle(self.title)
def increase(self, inc):
self.progressBar.setProperty("value", inc)
time.sleep(0.01)
def run(self):
for i in range(1,101):
self.increase(i)
progressThread = progressBar(QtGui.QApplication.activeWindow())
progressThread.start()
这似乎是 运行在线程内部正确设置了进度条,但它完全由 运行 函数控制。
我尝试删除 运行 函数并将此代码添加到我的主线程:
progressThread = progressBar(QtGui.QApplication.activeWindow())
progressThread.start()
for i in range(1,101):
progressThread.increase(i)
但这似乎不起作用。
任何帮助都将非常有用...谢谢
我相信 , and 已经在他们的评论中为您提供了关键信息。
正如他们已经说过的那样,如果主线程上有 UI 运行,您绝对可以 运行 您的进度条和您的逻辑在单独的线程中。
这里有一个示例,它应该可以按照您想要的方式工作:
import time, random
import threading
from PySide import QtCore, QtGui
class ProgressWidget(QtGui.QWidget):
# just for the purpose of this example,
# define a fixed number of threads to run
nthreads = 6
def __init__(self):
super(ProgressWidget, self).__init__()
self.threads = []
self.workers = []
self.works = [0 for i in range(self.nthreads)]
self.setupUi()
self.setupWorkers()
self.runThreads()
def drawProgessBar(self):
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setGeometry(QtCore.QRect(20, 20, 582, 24))
self.progressBar.minimum = 1
self.progressBar.maximum = 100
self.progressBar.setValue(0)
def setupUi(self):
self.setWindowTitle("Threaded Progress")
self.resize(600, 60)
self.drawProgessBar()
def buildWorker(self, index):
"""a generic function to build multiple workers;
workers will run on separate threads and emit signals
to the ProgressWidget, which lives in the main thread
"""
thread = QtCore.QThread()
worker = Worker(index)
worker.updateProgress.connect(self.handleProgress)
worker.moveToThread(thread)
thread.started.connect(worker.work)
worker.finished.connect(thread.quit)
QtCore.QMetaObject.connectSlotsByName(self)
# retain a reference in the main thread
self.threads.append(thread)
self.workers.append(worker)
def setupWorkers(self):
for i in range(self.nthreads):
self.buildWorker(i)
def runThreads(self):
for thread in self.threads:
thread.start()
def handleProgress(self, signal):
"""you can add any logic you want here,
it will be executed in the main thread
"""
index, progress = signal
self.works[index] = progress
value = 0
for work in self.works:
value += work
value /= float(self.nthreads)
# management of special cases
if value >= 100:
self.progressBar.hide()
return
# else
self.progressBar.setValue(value)
print 'progress (ui) thread: %s (value: %d)' % (threading.current_thread().name, value)
class Worker(QtCore.QObject):
"""the worker for a threaded process;
(this is created in the main thread and
then moved to a QThread, before starting it)
"""
updateProgress = QtCore.Signal(tuple)
finished = QtCore.Signal(int)
def __init__(self, index):
super(Worker, self).__init__()
# store the Worker index (for thread tracking
# and to compute the overall progress)
self.id = index
def work(self):
for i in range(100):
print 'worker thread: %s' % (threading.current_thread().name, )
# simulate some processing time
time.sleep(random.random() * .2)
# emit progress signal
self.updateProgress.emit((self.id, i + 1))
# emit finish signal
self.finished.emit(1)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = ProgressWidget()
ui.show()
sys.exit(app.exec_())
这是一个最小的细分:
- QThreads 存在于创建它们的主线程中(而不是在它们管理的线程中)
- 为了 运行 单独线程上的任务,必须使用
moveToThread
方法将它们传递给 QThreads(工作人员需要子类化 QObject
才能使该方法可用)
- 工作人员发送信号以更新进度条并通知他们完成任务
- 在这个例子中,我们 运行 执行多个任务,每个任务都在自己的线程中。进度信号被发送回主线程,其中更新进度条的逻辑运行s
旁注:在控制台中,工作人员的输出指的是 "dummy" 个线程。这似乎与 threading
模块不了解 QThreads 这一事实有关(至少我是从 here 那里得到的)。
不过,这似乎足以证明工作人员的任务 运行 在不同的线程上进行。如果谁有更准确的信息,欢迎补充。
对于那些想阅读更多关于这个主题的人,here is a link 许多文章都提到了。
我想 运行 在与我的其余代码不同的线程中创建一个进度条,但我想控制进度条如何从我的主线程更新。
这是可能的吗?
这是我目前拥有的:
import time
from PySide import QtGui
from PySide import QtCore
from PySide import QtUiTools
class progressBar(QtGui.QDialog, QtCore.QThread):
def __init__(self, window, title=None):
super(progressBar, self).__init__(window)
QtCore.QThread.__init__(self)
self.title = title or 'Progress'
self.setupUi()
self.show()
def setupUi(self):
self.setObjectName("Thinking")
self.gridLayout = QtGui.QGridLayout(self)
self.gridLayout.setObjectName("gridLayout")
self.progressBar = QtGui.QProgressBar(self)
self.gridLayout.addWidget(self.progressBar, 0, 0, 1, 1)
# ADJUSTMENTS
self.setMaximumSize(280, 50)
self.setMinimumSize(280, 50)
self.setWindowTitle(self.title)
def increase(self, inc):
self.progressBar.setProperty("value", inc)
time.sleep(0.01)
def run(self):
for i in range(1,101):
self.increase(i)
progressThread = progressBar(QtGui.QApplication.activeWindow())
progressThread.start()
这似乎是 运行在线程内部正确设置了进度条,但它完全由 运行 函数控制。
我尝试删除 运行 函数并将此代码添加到我的主线程:
progressThread = progressBar(QtGui.QApplication.activeWindow())
progressThread.start()
for i in range(1,101):
progressThread.increase(i)
但这似乎不起作用。
任何帮助都将非常有用...谢谢
我相信
这里有一个示例,它应该可以按照您想要的方式工作:
import time, random
import threading
from PySide import QtCore, QtGui
class ProgressWidget(QtGui.QWidget):
# just for the purpose of this example,
# define a fixed number of threads to run
nthreads = 6
def __init__(self):
super(ProgressWidget, self).__init__()
self.threads = []
self.workers = []
self.works = [0 for i in range(self.nthreads)]
self.setupUi()
self.setupWorkers()
self.runThreads()
def drawProgessBar(self):
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setGeometry(QtCore.QRect(20, 20, 582, 24))
self.progressBar.minimum = 1
self.progressBar.maximum = 100
self.progressBar.setValue(0)
def setupUi(self):
self.setWindowTitle("Threaded Progress")
self.resize(600, 60)
self.drawProgessBar()
def buildWorker(self, index):
"""a generic function to build multiple workers;
workers will run on separate threads and emit signals
to the ProgressWidget, which lives in the main thread
"""
thread = QtCore.QThread()
worker = Worker(index)
worker.updateProgress.connect(self.handleProgress)
worker.moveToThread(thread)
thread.started.connect(worker.work)
worker.finished.connect(thread.quit)
QtCore.QMetaObject.connectSlotsByName(self)
# retain a reference in the main thread
self.threads.append(thread)
self.workers.append(worker)
def setupWorkers(self):
for i in range(self.nthreads):
self.buildWorker(i)
def runThreads(self):
for thread in self.threads:
thread.start()
def handleProgress(self, signal):
"""you can add any logic you want here,
it will be executed in the main thread
"""
index, progress = signal
self.works[index] = progress
value = 0
for work in self.works:
value += work
value /= float(self.nthreads)
# management of special cases
if value >= 100:
self.progressBar.hide()
return
# else
self.progressBar.setValue(value)
print 'progress (ui) thread: %s (value: %d)' % (threading.current_thread().name, value)
class Worker(QtCore.QObject):
"""the worker for a threaded process;
(this is created in the main thread and
then moved to a QThread, before starting it)
"""
updateProgress = QtCore.Signal(tuple)
finished = QtCore.Signal(int)
def __init__(self, index):
super(Worker, self).__init__()
# store the Worker index (for thread tracking
# and to compute the overall progress)
self.id = index
def work(self):
for i in range(100):
print 'worker thread: %s' % (threading.current_thread().name, )
# simulate some processing time
time.sleep(random.random() * .2)
# emit progress signal
self.updateProgress.emit((self.id, i + 1))
# emit finish signal
self.finished.emit(1)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = ProgressWidget()
ui.show()
sys.exit(app.exec_())
这是一个最小的细分:
- QThreads 存在于创建它们的主线程中(而不是在它们管理的线程中)
- 为了 运行 单独线程上的任务,必须使用
moveToThread
方法将它们传递给 QThreads(工作人员需要子类化QObject
才能使该方法可用) - 工作人员发送信号以更新进度条并通知他们完成任务
- 在这个例子中,我们 运行 执行多个任务,每个任务都在自己的线程中。进度信号被发送回主线程,其中更新进度条的逻辑运行s
旁注:在控制台中,工作人员的输出指的是 "dummy" 个线程。这似乎与 threading
模块不了解 QThreads 这一事实有关(至少我是从 here 那里得到的)。
不过,这似乎足以证明工作人员的任务 运行 在不同的线程上进行。如果谁有更准确的信息,欢迎补充。
对于那些想阅读更多关于这个主题的人,here is a link 许多文章都提到了。