1

I'm trying to write a PyQt application for some image processing algorithms that I have written. The problem is, these take some time and make the app freezes (until it finishes but the user might be compelled to close the app in the mean time).

I'm trying to understand how to implement multi-threading but I just can't seem to make it work. This example just loads a large image on a different thread, but it still makes the whole app freeze. I'm sure I'm making a mistake somewhere.

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class App(QWidget):
    def __init__(self):
       super().__init__()
       self._unit_ui()

    def _unit_ui(self):
        label = QLabel(self)
        label.resize(700, 700)

        button = QPushButton(self)

        self.th = Thread(self)
        self.th.change_pixmap.connect(label.setPixmap)
        button.pressed.connect(self.th.start)

        self.show()


class Thread(QThread):
    change_pixmap = pyqtSignal(QPixmap)

    def __init__(self, parent=None):
        QThread.__init__(self, parent=parent)
        self.isRunning = True

    def run(self):
        pixmap = QPixmap('gridscan.jpg')
        self.change_pixmap.emit(pixmap)



app = QApplication(sys.argv)
m = App()
sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Felipe Moser
  • 323
  • 4
  • 19
  • What size is the image ?, On the other hand you should not use QPixmap in another thread, use QImage in that other thread and send it to the main thread, in the main thread convert it to QPixmap, for more information read the following: http://doc.qt.io/qt-5/thread-basics.html#gui-thread-and-worker-thread – eyllanesc Jun 05 '18 at 12:12
  • the image is a 25000x25000 jpg. Is there a way to pass the image (np.array) instead of the QPixmap? When i changed the signal to QObject and passed the image it crashes python – Felipe Moser Jun 05 '18 at 12:35

2 Answers2

1

With the help of eyllanesc I managed to solve it. I just stopped using QPixmap in my second thread and imported the image with another function, passed it (changing the pyqtSignal(QPixmap) to pyqtSignal(np.ndarray)) and now it works flawlessly! Thanks!

Felipe Moser
  • 323
  • 4
  • 19
0

You can try looking into this answer: https://stackoverflow.com/a/38003561/9066493

Basically, self.th needs to be moved to a different thread like:

# Setup the worker object and the worker_thread.
self.worker = WorkerObject()
self.worker_thread = QtCore.QThread()
self.worker.moveToThread(self.worker_thread)
self.worker_thread.start()

And then transfer data between the main thread and the worker thread using signal and slots, which you need to connect to a specific method slot

Hope the example helps.

bfontaine
  • 18,169
  • 13
  • 73
  • 107
aeroaks
  • 1
  • 4
  • The result will be the same, there are 2 approaches of the same solution, I think the problem is not in that but in the size of the image, the secondary thread will help in the processing but if the image is very large the GUI will freeze from any way. It could indicate the advantage and improvement of your solution. – eyllanesc Jun 05 '18 at 12:14