I would like to run the QProgressDialog on the Pyside on a different thread.

Asked 2 years ago, Updated 2 years ago, 18 views

As stated in the title, I want to run QProgressDialog on a different thread, but I am having trouble because it is not stable.
I'd like to have the dialog not stiffen while performing heavy third-party processing.
What I want to do is basically a script like this:
(Third-party modules are commented out)

#-*-coding:utf-8-*-
import sys
from PySide import QtCore, QtGui
import time
# import third_party_module


def start_third_party_module():
    item_num=3

    d=QtGui.QProgressDialog()
    d.setRange(0,item_num)
    d.show()

    for i in range(item_num):
        # There's a heavy process here.
        # third_party_module.do(i)
        d. setValue(i)
        print i
        time.sleep(2)

class MainWindow (QtGui.QMainWindow):
    def__init__(self, parent=None):
        super(MainWindow,self).__init__()
        button=QtGui.QPushButton(self)
        button.setText("Click me")
        button.clicked.connect(self.pushBtn)

    def pushBtn(self):
        start_third_party_module()

defmain():
    qApp = QtGui.QApplication(sys.argv)
    win=MainWindow(qApp)
    win.show()
    sys.exit(qApp.exec_())

main()

If you run the above script, the dialog will be displayed, but it is inconvenient that you cannot press the cancel button.
I have also tried running third-party modules in QThread, but it is not stable (frequently drops), and I would like to run third-party modules in the main and touch the progress dialog.

Thank you for your help.

Note: The above script was too broken last time, so I added some information.
Thank you for your cooperation.

python

2022-09-30 19:01

3 Answers

I think it's not because of the heavy handling, but because of how to display the QProgressDialog.
Specifically, I think the reason is that MainWindow.pushBtn and later have a series of processes.

If you change two places, you will be able to update and operate the QProgressDialog.

(with heavy handling)

Connect method for button.
Make the following changes:

#Before change
    button.clicked.connect(self.pushBtn)
    # after modification
    button.clicked.connect (self.pushBtn, QtCore.Qt.QueuedConnection)

How to view dialog.
Instead of displaying it in pushBtn or later processing, display it outside of it.
Specifically, the QProgressDialog object should be a member of MainWindow and connected to button.clicked to display it.

# Changed (in MainWindow.__init__)
    self.dialog=QProgressDialog()
    button.clicked.connect(dialog.show)

The reason is that button.clicked events are taking a series of actions (MainWindow.pushBtn or later actions), so the action does not return to the event dispatcher.(Other events will not be processed unless you return)
Therefore, make the former changes to make the button.clicked event work to put the event in the event queue.
Similarly, make the latter change to allow event dispatch in QtGui.QProgressDialog.

# For the second argument of connect, see the Qt.ConnectionType document.


2022-09-30 19:01

I made the script as simple as possible and added @user20098.
I also checked how QtCore.Qt.QueuedConnection works.
I don't know how to put it together from here...
(In the script below, the QProgressDialog appears solid white and
Progress bar or cancel button appears after MainWindow.pushBtn is processed)

#-*-coding:utf-8-*-

import sys
from PySide import QtCore, QtGui
import time

class MainWindow (QtGui.QMainWindow):
    def__init__(self, parent=None):
        super(MainWindow,self).__init__()

        button=QtGui.QPushButton(self)
        button.setText("Click me")
        button.clicked.connect (self.pushBtn, QtCore.Qt.QueuedConnection)

        self.dialog=QtGui.QProgressDialog()
        button.clicked.connect (self.dialog.show)

    def pushBtn(self):    
        for i in range (3):
            print i
            time.sleep(2)


defmain():
    qApp = QtGui.QApplication(sys.argv)
    win=MainWindow(qApp)
    win.show()
    sys.exit(qApp.exec_())

main()

Will it be combined with QThread processing?
I apologize for my lack of understanding, but I appreciate your cooperation.m(__)m


2022-09-30 19:01

Calling QtGui.QApplication.processEvents() in the for loop in pushBtn() will improve your response a little more.

#Example Code
    # In the MainWindow constructor, create a QApplication object.
    # Since it is taken as an argument, it is assumed that it is stored as self.a.
    def pushBtn(self):
        for i in range (3):
            print i
            a.processEvents()
            time.sleep(2)

*

Even in this case, I don't think I will get a response to the operation during the heavy operation (which I expect to do in time.sleep(2)), so I think I will disconnect the heavy operation with QThread.


2022-09-30 19:01

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.