0

According this example : link ,I want to implement a thread based small application within a GUI. I have two files TestMain.py and TestManager.py (Worker class), which are connected with each other over sys.path.append('...'). In TestMain.py, I load my GUI, create thread and signal/slot connections, which act on functions in TestManager.py. In TestManager.py I do some calculations and want to visualize them in a QTextEditor at the same time. To do this, I have written following code:

TestMain.py

sys.path.append('../app/source')
from TestManager import *

class TestMain(QMainWindow):
    def __init__(self, parent= None):
        super(TestMain, self).__init__(parent)

        self.manager= TestManager()
        self.thread= QThread()
        self.manager.moveToThread(self.thread)

        self.manager.finished.connect(self.thread.quit)
        self.thread.started.connect(self.manager.first_slot)
        self.thread.start()

        self.manager.printFirstSignal.connect(self.print_onTextEdit)

        self.offlinePushButton.clicked.connect(self.offline_slot)

    def offline_slot(self):
        manager.do_some_calc(self)

    def print_onTextEdit(self, str):
        self.outputTextEdit.append(str)

Manager.py

sys.path.append('../app/source')
from TestMain import *

class TestManager(QObject): #QtCore.QThread
    finished= pyqtSignal()
    printFirstSignal= pyqtSignal(str)

    def __init__(self, parent= None):
        super(TestManager, self).__init__(parent)

    def first_slot(self):
        self.printFirstSignal.emit('TEST')
        self.finished.emit()

    def do_some_calc(self):
        do_someting()
        TestManager.first_slot("do_some_calc")

If I do self.thread.started.connect(self.manager.first_slot) in TestMain and emit the pyqtSignal in function first_slot() in TestManager, then I can update my GUI without any problem. But if I call a slot (e.g do_some_calc()) in TestManager and want to also update the GUI from there, than I get a segmentation fault. Even if I create a separate signal for this function, it does not work. Cause I call this function in TestMain self.offlinePushButton.clicked.connect(self.offline_slot)

My question is. How can I call any function in TestManager internally or from MainTest so that I can still update the GUI?

Thank you for any suggestion

nasil122002
  • 127
  • 1
  • 3
  • 15
  • Hi, could you provide a minimal and runnable app of what you are trying to do ? – Yohboy Feb 15 '18 at 14:23
  • You can only update the gui from the main thread. If `TestManager` needs to trigger a gui update, you will need to send a signal back to `TestMain` and have it handle the update. – user3419537 Feb 15 '18 at 14:47
  • Actually I did it exactly. I have defined a signal in `TestManager` as ` testSignal= pyqtSignal(str)` and emitted in `def do_some_calc(self):` function like `self.testSignal.emit('Some str')`. In `TestMain` connected the signal like `self.manager.testSignal.connect(self.print_onTextEdit2)`. and defined function: `def print_onTextEdit2(self, value): self.outputTE.append(value)`. The app crashes exactly, where I emit the signal in `TestManager` – nasil122002 Feb 15 '18 at 15:41
  • Then I would guess there is some small mistake in your code. If you have an unhandled exception inside a PyQt slot it will crash your program, rather than print a traceback like you would expect. I suggest you wrap your slot code inside `try/except` blocks and print any captured errors to pinpoint the problem – user3419537 Feb 15 '18 at 17:16
  • @nasil122002. One way or another, you **must** use signals to communicate between threads. – ekhumoro Feb 15 '18 at 19:46
  • Ok from expectation: ` try: self.testSignal.emit('Some str') except: e = sys.exc_info() print('Exception :', e)` I get: `Exception : (, AttributeError("'TestMain' object has no attribute 'testSignal'",), )` What it means? The signal is defined where it is called also in `TestManager` class. Why should have it somewhere else? – nasil122002 Feb 15 '18 at 19:47

0 Answers0