7

I have a QGIS plugin and would like to put loading GIF (spinner) somewhere in the Dialog Window. The problem is when I run the spinner with the following code and call next function, the spinner freezes and activates only when process finishes. The dialog.py looks like the following:

class DEDialog(QtWidgets.QDialog, FORM_CLASS):
  def __init__(self, parent=None):
    super(DEDialog, self).__init__(parent)
    self.setupUi(self)
    self.run_button = self.findChild(QtWidgets.QPushButton, 'pushButton')
    self.run_button.clicked.connect(self.pipeline)
    self.a = 1
    self.b = 2
    self.c = 3

  def pipeline(self):
    self.gif = 'C:\\Users\\User\\1474.gif'
    self.movie = QMovie(self.gif)
    self.label.setGeometry(QtCore.QRect(25, 25, 850, 850))
    self.label.setMinimumSize(QtCore.QSize(200, 200))
    self.movie.setCacheMode(QMovie.CacheAll)
    self.label.setMovie(self.movie)
    self.movie.start()

    self.do()

def do(self):
    self.do_ground = FunctionFromFile(self.a, self.b, self.c)

I know that there is something like multithreading but I still don't understand how to realise it with PyQt5 correctly.

UPD. Now I have the following code, which is actually works not as I want:

    class DEDialog(QtWidgets.QDialog, FORM_CLASS):
      def __init__(self, parent=None):
        """Constructor."""
        super(DEDialog, self).__init__(parent)
        self.run_button = self.findChild(QtWidgets.QPushButton, 'pushButton')
        self.run_button.clicked.connect(self.pipeline)

    def show_movie(self, task):
        self.gif = 'C:\\Users\\User\\Downloads\\1474.gif'
        self.movie = QMovie(self.gif)
        self.label.setGeometry(QtCore.QRect(25, 25, 850, 850))
        self.label.setMinimumSize(QtCore.QSize(200, 200))
        self.label.setMovie(self.movie)
        self.movie.start()
        return 5

    def pipeline(self):
        mgr = QgsTaskManager()
        task = QgsTask.fromFunction('my_task', self.show_movie,
                                    on_finished=calculation_finished)
        mgr.addTask(task)
        print("added movie")

        task1 = QgsTask.fromFunction('my_task1', calculate,
                                    on_finished=calculation_finished)
        mgr.addTask(task1)
        print("added task")

def calculate(task):
    return 5 * 6

def calculation_finished(exception, value=None):
    if not exception:
        print(
            'the magic number is {}'.format(value))
    else:
        print(
            str(exception))

The problem is that I have to do countings after adding .addTask or the task will be cancelled. Another problem is that task will start only after main program in the pipeline finishes and I want to make them parallel.

0

1 Answer 1

1

The task manager must be returned from QgsApplication.taskManager() function.

So in the function called pipeline you should do this.

def pipeline(self):
    # mgr = QgsTaskManager()
    mgr = QgsApplication.taskManager() # get the task manager
    task = QgsTask.fromFunction('my_task', self.show_movie,
                                on_finished=calculation_finished)
    mgr.addTask(task)
    print("added movie")
    task1 = QgsTask.fromFunction('my_task1', calculate,
                                on_finished=calculation_finished)
    mgr.addTask(task1)
    print("added task")

This could also be done with the python threading module. Here you can find some useful posts:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.