PySide和QProgressBar在不同的线程中更新 [英] PySide and QProgressBar update in a different thread

查看:110
本文介绍了PySide和QProgressBar在不同的线程中更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是一篇长文章,所以,在此先感谢与我在一起直到最后.这里的问题是(我认为这是一个非常基本的问题,只是我对PiSide和Qt的经验不足,这使我更难了.)我有一个带有一个菜单项的主窗口,假设为"Process".代码如下-

This may be a little long post, so, thanks in advance to be with me till the end. Here is the problem, (i think a fairly basic one, just my inexperience with PiSide and Qt making it harder for me.) I have a main window with one menu item, suppose "Process". the code is following -

from PySide import QtCore, QtGui

class Ui_MainWindow(object):

      def setupUi(self, MainWindow, AppObj):
            .
            .
            self.statusbar = QtGui.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            .
            .
            .
           self.actionProcess = QtGui.QAction(MainWindow)
           self.actionProcess.setObjectName("actionProcess")
           self.actionProcess.triggered.connect(self.myappObj.menuActionProcess) 
           .

在这里self.myappobj指的是我创建的一个应用程序类,它充当我的应用程序的主要逻辑控制器.代码-

Here self.myappobj refers to a app class I have created which acts as the main logic controller for my app. The code -

from PySide import QtCore, QtGui
from MainWindow import Ui_MainWindow

class App(QtGui.QDialog):
      def __init__(self, parent=None):
          self.__mainWindow = QtGui.QMainWindow()
          self.__mainWindowDesignContext = Ui_MainWindow()
          self.__mainWindowDesignContext.setupUi(self.__mainWindow, self)
          self.__mainWindow.show()
      def menuActionProcess(self):
          self.processThread = BatchProcesser()
          self.progressBar = QtGui.QProgressBar()
          statusBar.addWidget(self.progressBar)
          self.progressBar.show()
          self.progressBar.setMinimum(0)
          self.progressBar.setMaximum(100)
          QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)
          if not self.processThread.isRunning():
              self.processThread.exiting = False
              self.processThread.start()

因此,很容易看出我在这里要做的是创建一个主窗口.在其中添加一个名为"Process"的菜单,单击该菜单应触发应用程序类中的回调menuActionProcess方法,在其中创建一个进度条,并将其附加到主窗口的状态栏中(实际代码还有很多其他内容,我在这里给出的是重新排列的必要部分,以作为一个伪示例) 最后在上述代码中提到的BatchProcesser类中,我正在执行此操作-

So, it is easy to see that what i am trying to do here is to create a main window. Add a menu there called "Process", clicking on which should trigger the callback menuActionProcess method in the app class, where I am making a progress bar and attaching it with the Status Bar of my main window (The actual code has many other things, what i give here is the necessary parts rearranged as an pseudo example) and finally in the BatchProcesser class mentioned in the above code, I am doing this -

from PySide.QtGui import *
from PySide.QtCore import *

class BatchProcesser(QThread):
     __errorHappened = False
     def __init__(self, parent=None):
         QThread.__init__(self, parent)
         self.exiting = False
     def run(self):
         for a in range(101):
            print a
            QThread.msleep(100)
            self.emit(SIGNAL("progress(int)"), a)
            print a

据我所知,这应该在与主线程不同的线程中更新附加到状态栏的进度条.这将允许用户自由地与GUI交互.

In my understanding this should update the Progress Bar attached to the Status Bar in a different thread than the main thread. This will allow the user to interact with the GUI freely.

现在,如果我尝试冲洗它,一切都很好,直到我点击处理"菜单.然后,进度条会平缓,但不会更新,并且控制台已满,并显示错误-

Right now, If i try to rin this, everything is fine until i hit the Process menu. Then, the progress bar appeases but does not update and the console is full with error -

0 QPixmap:在GUI线程外使用像素图是不安全的

0 QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

0

1

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

QPixmap:在GUI线程外使用像素图是不安全的

QPixmap: It is not safe to use pixmaps outside the GUI thread

[xcb]出队时队列中的未知请求

[xcb] Unknown request in queue while dequeuing

[xcb]最有可能是多线程客户端,并且XInitThreads具有 没有被叫

[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called

[xcb]正在中止,对此感到抱歉.

[xcb] Aborting, sorry about that.

python:../../src/xcb_io.c:178:dequeue_pending_request:断言 `!xcb_xlib_unknown_req_in_deq'失败.

python: ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.

已中止(核心已弃用)

我非常需要任何帮助.我无法找出和/或指出错误的原始原因并解决该问题.

Any help is very much required for me. I am unable to find out and/ot point the original reason of the error and fix the same.

推荐答案

问题在于如何将信号连接到插槽:

The problem lies in how you connect the signal to the slot:

      QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)

在这里,您明确地强制执行DirectConnection.这是错的!它使该插槽在调用者的线程中得到处理.这意味着progressBar的GUI更新发生在进程线程中,而不是在GUI线程中.但是,仅在GUI线程中允许绘图.

Here, you explicitely enforce a DirectConnection. This is wrong! It makes the slot be processed in the caller's thread. This means that the GUI update of the progressBar happens in the process thread, not in the GUI thread. However, drawing is only allowed in the GUI thread.

将信号从一个线程连接到另一个线程的插槽是完全可以的.但是,您需要AutoConnection(默认值,它将识别线程并使用QueuedConnection)或QueuedConnection.

It is perfectly fine to connect a signal from one thread to a slot from another. However, you need either AutoConnection (the default, which will recognize the threads and use QueuedConnection) or QueuedConnection.

此行应解决您的问题:

      QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.QueuedConnection)

请参见 http://doc.qt.io/archives /qt-4.7/qt.html#ConnectionType-枚举.

这篇关于PySide和QProgressBar在不同的线程中更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆