Python PyQT:如何从工作线程调用GUI函数? [英] Python PyQT: How to call a GUI function from a worker thread?
问题描述
Thx为任何帮助!
导入线程,pexpect
self.cmd_list = [ 'ffmpeg -i file outfile','等等]
self.stop_proc = False
self.executeCMD()
def spawn_ffmpeg_cmd(self)
for cmd in self.cmd_list:
if self.stop_proc == False:
thread = pexpect.spawn(cmd)
打印\\\
started:%s%cmd
cpl = thread.compile_pattern_list([pexpect.EOF,frame = * \d + fps = * \d +,'(。+)'])
while True:
i = thread.expect_list(cpl,timeout = None)
如果i == 0:#EOF
打印子进程退出
self.pgticker + = 1
break
elif i == 1:
frame_number_fps = thread.match.group(0)
print frame_number_fps
thread.close
elif i == 2:
pass
self.startButton.setEnabled(True)
def executeCMD(self):
self.startButton.setEnabled (False)
self.pgticker = 0
threading.Thread(target = self.spawn_ffmpeg_cmd,name =_ proc)。start()
def stopprocess (self):
self.stop_proc = True
self.cmd_list = []
os.system('pkill ffmpeg')
self.pgticker = len(self.cmd_list)
self.startButton.setEnabled(True)
def updateProgress(self):
pgfactor = 100 / len(self.cmd_list)
progress = 0.0
progress = pgfactor * int(self.pgticker)
self.progressBar.setProperty(value,progress)
简而言之:移动到 QThread
并使用Qt的信号和插槽,在线程之间进行通信的方式。
这个答案提供了一些这样的例子:
https://stackoverflow.com/a/6789205/2319400
在你的情况下,使用上面的SomeObject版本可能如下所示:
class Worker QtCore.QObject):
madeProgress = QtCore.pyqtSignal([int])
finished = QtCore.pyqtSignal()
def __init __(self,cmdlist)
self.cmdlist = cmdlist
def run(self):
for icmd,cmd in enumerate(self.cmdlist):
#执行你的工作
#processCommand(cmd)
#我们已经取得进展的信号
self.madeProgress.emit(icmd)
#发出完成的信号 - 重新完成
self.finished.emit()
然后将此工作人员移动到 QThread
您创建的实例。
按照链接答案的模式,您可以将 madeProgress
信号
连接到 setValue
进度条的插槽:
workerThread = QThread()
workerObject = Worker(cmdlist)
workerObject.moveToThread(workerThread)
workerThread.started.connect(workerObject.run)
workerObject.finished.connect(workerThread.quit)
#创建一个具有最小/最大值根据
#你的cmdlist的长度
progressBar = QProgressBar()
progressBar.setRange(0,len(cmdlist))
#连接工作进度信号与进度条
workerObject.madeProgress.connect(progressBar.setValue)
#启动线程(同时启动您的工作)
workerThread.start()
I have a pyqt gui and calling a long process (ffmpeg) which I put on a separate thread to not block the gui. I then want to update a progress bar when one command of a longer list of commands finishes. The problem is, that I can't call a function in the gui thread out of the worker thread. So I let run a ticker in the worker thread, but when I update the progress bar with a while loop and reading the ticker value, the gui gets blocked again. How can I solve this. I used currently python threading and not Qthread. Thx for any help!
import threading, pexpect
self.cmd_list = ['ffmpeg -i file outfile','and so on']
self.stop_proc = False
self.executeCMD()
def spawn_ffmpeg_cmd(self):
for cmd in self.cmd_list:
if self.stop_proc == False:
thread = pexpect.spawn(cmd)
print "\nstarted: %s" % cmd
cpl = thread.compile_pattern_list([pexpect.EOF,"frame= *\d+ fps=*\d+",'(.+)'])
while True:
i = thread.expect_list(cpl, timeout=None)
if i == 0: # EOF
print "the sub process exited"
self.pgticker += 1
break
elif i == 1:
frame_number_fps = thread.match.group(0)
print frame_number_fps
thread.close
elif i == 2:
pass
self.startButton.setEnabled(True)
def executeCMD(self):
self.startButton.setEnabled(False)
self.pgticker = 0
threading.Thread(target=self.spawn_ffmpeg_cmd, name="_proc").start()
def stopprocess(self):
self.stop_proc = True
self.cmd_list = []
os.system('pkill ffmpeg')
self.pgticker = len(self.cmd_list)
self.startButton.setEnabled(True)
def updateProgress(self):
pgfactor = 100 / len(self.cmd_list)
progress = 0.0
progress = pgfactor*int(self.pgticker)
self.progressBar.setProperty("value", progress)
In short: Move to QThread
and use Qt's signals and slots, they are the preferred way to communicate between threads.
This answer provides some examples how this could look like: https://stackoverflow.com/a/6789205/2319400
In your case, using the "SomeObject" version from the above could look like this:
class Worker(QtCore.QObject):
madeProgress = QtCore.pyqtSignal([int])
finished = QtCore.pyqtSignal()
def __init__(self, cmdlist):
self.cmdlist = cmdlist
def run(self):
for icmd, cmd in enumerate(self.cmdlist):
# execute your work
# processCommand(cmd)
# signal that we've made progress
self.madeProgress.emit(icmd)
# emit the finished signal - we're done
self.finished.emit()
Then move this worker to a QThread
instance you create.
Following the pattern from the linked answer, you can then connect the madeProgress
signal
to the setValue
slot of a progressbar:
workerThread = QThread()
workerObject = Worker(cmdlist)
workerObject.moveToThread(workerThread)
workerThread.started.connect(workerObject.run)
workerObject.finished.connect(workerThread.quit)
# create a progressbar with min/max according to
# the length of your cmdlist
progressBar = QProgressBar()
progressBar.setRange(0, len(cmdlist))
# connect the worker's progress signal with the progressbar
workerObject.madeProgress.connect(progressBar.setValue)
# start the thread (starting your worker at the same time)
workerThread.start()
这篇关于Python PyQT:如何从工作线程调用GUI函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!