我正在尝试学习如何在PyQt Gui应用程序中使用QThreads.我有一些运行一段时间的东西,有(通常)点我可以更新一个Gui,但我想将主要工作拆分到它自己的线程(有时候东西会卡住,最终会有一个很好的取消/再试一次按钮,如果由于主循环被阻止,Gui被冻结,这显然不起作用).
我已阅读https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/.该页面说重新实现该run方法不是这样做的方法.我遇到的问题是找到一个PyQt示例,其中有一个主线程正在执行Gui,而一个工作线程没有这样做.这篇博文是针对C++的,所以虽然它的例子确实有帮助,但我仍然有点失落.有人可以请给我一个在Python中正确方法的例子吗?
上下文:在Python中,主线程产生第二个进程(使用多处理模块),然后启动GUI(使用PyQt4).此时主线程将阻塞,直到GUI关闭.第二个过程总是处理,理想情况下应该以异步方式将信号发送到GUI中的特定插槽.
问题:Python和PyQt4中有哪些方法/工具可以实现这些以及如何实现?优选地,以软中断方式而不是轮询.
抽象地说,我能想到的解决方案是在主线程中实例化的"工具/处理程序",它抓取GUI实例中的可用插槽并连接来自第二个进程的抓取信号,假设我提供了这个工具的一些信息期待或硬编码.这可以实例化为第三个进程/线程.
我在PyQt中有一个带有函数的GUI addImage(image_path).很容易想象,当应该将新图像添加到QListWidget中时调用它.为了检测文件夹中的新图像,我使用threading.Threadwith watchdog来检测文件夹中的文件更改,然后该线程addImage直接调用.
QPixmap由于线程安全的原因,这会产生不应在gui线程外部调用的警告.
使线程安全的最佳和最简单的方法是什么?QThread的?信号/插槽?QMetaObject.invokeMethod?我只需要从线程传递一个字符串addImage.
我正在(仍然)使用书籍装订应用程序,并且为了使其美观,我已经为你拖入的每个页面添加了一个缩略图.它工作正常,但唯一的问题是当我拖入一个整体书(即400张图片),它完全冻结,直到它完成.
这是我的简单删除代码:
def fileDropped(self, file):
f = str(file[-1])
if os.path.splitext(f)[1][1:] != 'tif':
reply = QtGui.QMessageBox.question(self, 'Message', 'All files must be TIF images. Would you like me to convert a copy of your file to the TIF format?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
if not os.path.exists('./djvu_backup/'): os.mkdir('./djvu_backup/')
if f not in self.getChildren(self.ui.pageList): # It's a custom method. It does what it looks like it does.
icon = QtGui.QIcon(f)
pixmap = icon.pixmap(72, 72)
icon = QtGui.QIcon(pixmap)
item …Run Code Online (Sandbox Code Playgroud) 我有一个GUI应用程序,需要从GUI主循环旁边的网络中获取和解析各种资源.我使用python多处理模块搜索了选项,因为这些获取操作不仅包含阻塞IO而且还包含大量解析,因此多处理可能比python线程更好.使用Twisted会很容易,但这次Twisted不是一个选项.
我找到了一个简单的解决方案:
问题是在MainThread中没有调用回调.
所以我想出了以下解决方案:
delegate.py
import os
import multiprocessing as mp
import signal
from collections import namedtuple
import uuid
import logging
_CALLBACKS = {}
_QUEUE = mp.Queue()
info = logging.getLogger(__name__).info
class Call(namedtuple('Call', 'id finished result error')):
def attach(self, func):
if not self.finished:
_CALLBACKS.setdefault(self.id, []).append(func)
else:
func(self.result or self.error)
return self
def callback(self):
assert self.finished, 'Call not finished yet'
r = self.result or self.error
for func in _CALLBACKS.pop(self.id, []):
func(r)
def done(self, result=None, error=None):
assert not self.finished, 'Call already finished' …Run Code Online (Sandbox Code Playgroud) 使用Python3和PyQt4我有一个函数(运行),它将一个可调用的输入作为输入来提供状态更新.
class Windows(QtGui.QWidget):
# Creates a widget containing:
# - a QLineEdit (status_widget)
# - a button, connected to on_run_clicked
def on_run_clicked(self):
def update(text):
self.widget.setText(text)
threading.Thread(target=run, args=(update, )).start()
Run Code Online (Sandbox Code Playgroud)
这工作正常(即文本更新在小部件中正确显示).然而,当我更换QLineEdit的通过的QTextEdit并使用追加方法添加文本,我得到:
QObject :: connect:无法对"QTextCursor"类型的参数进行排队
(确保使用qRegisterMetaType()注册'QTextCursor'.)
它仍然有效,但指出我做错了什么,而且我不确定当更多线程处于活动状态时我会继续工作.通常,我使用信号和插槽进行此类更新,但run函数不是PyQt特定的.问题是:
我想知道与QThread相比,从QObject中的常规python线程发出信号会产生什么后果.
请参阅以下课程:
class MyObject(QtCore.QObject):
def __init__(self):
super().__init__()
sig = pyqtSignal()
def start(self):
self._thread = Thread(target=self.run)
self._thread.start()
def run(self):
self.sig.emit()
# Do something
Run Code Online (Sandbox Code Playgroud)
现在,假设在GUI线程中,我有:
def __init__(self):
self.obj = MyObject()
self.obj.sig.connect(self.slot)
self.obj.start()
def slot(self):
# Do something
Run Code Online (Sandbox Code Playgroud)
在slot当所述信号被发射确实执行.但是,我想知道该slot方法将在哪个线程中执行?如果我使用QThread而不是python线程,它会有什么不同MyObject吗?
我正在使用PyQt5和Python 3.
我在Python 3.5中遇到了PyQt5的奇怪问题。我有两个课,FrontEnd(QWidget)和TimerThread(Thread)。我QLabel在的init函数中定义了多个FrontEnd,所有都可以正常工作。
显示的是以下几个相关功能FrontEnd:
def update_ui(self):
ret, frame = self.cam_capture.read()
if self.results_pending:
if not path.isfile('output.jpg'):
self.results_pending = False
with open('.out') as content_file:
content = content_file.readlines()[2:-2]
system('rm .out')
self.handle_image_classification(content)
if self.take_picture:
cv2.imwrite('output.jpg', frame)
self.user_prompt.setText('Please wait...')
system('./classifyimage.py --mean mean.binaryproto --nogpu --labels labels.txt model.caffemodel deploy.prototxt output.jpg > .out && rm output.jpg')
self.take_picture = False
self.results_pending = True
image = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888).rgbSwapped()
pix = QPixmap.fromImage(image)
self.video_frame.setPixmap(pix)
def update_bar_graph(self, data):
palette = QPalette()
palette.setColor(QPalette.Background, …Run Code Online (Sandbox Code Playgroud)