Babak Khazaie
Babak Khazaie

Reputation: 83

Issues with Signal-Slot while using Qthread

I wrote a sample code for my issue. This code should produce sum of two given numbers and show the result in text-browser then replace first number with sum, and add it to second number and show the result in text-browser again.This process should continues. The issues are:

1 - Why signal is not working properly?

2 - How can i emit signal with sum-number to show on text-browser?

import sys
import time

from PyQt4.QtCore import *
from PyQt4.QtGui import *


class AreaThread(QThread):
    signal = pyqtSignal()

    def __init__(self, no1, no2, parent):
        QThread.__init__(self)

        self.no1 = no1
        self.no2 = no2

    def area(self):
        for i in range(10):
            self.sum = self.no1 + self.no2
            self.no1 = self.no2
            self.no2 = self.sum
            self.signalemit()
            time.sleep(1)

    def signalemit(self):
        self.signal.emit()

    def run(self):
        self.area()


class GeneralizedRun (QMainWindow):

    def __init__(self, no1, no2):

        QMainWindow.__init__(self)
        self.no1 = no1
        self.no2 = no2

    def initUi(self, mainwindow):

        mainwindow.centralWidget = QWidget(mainwindow)

        self.runflow = QTextBrowser()
        self.runflow.isReadOnly()
        self.runflow.setText('running:')
        self.runflow.moveCursor(QTextCursor.End)

        self.runflow.show()
        mainwindow.centralWidget = self.runflow
        self.threadruning()

    def threadruning(self):
        self.area = AreaThread(self.no1, self.no2, self)
        self.area.start()
        self.area.signal.connect(self.updatetexteditor)

    def updatetexteditor(self):

        self.runflow.insertPlainText('\n\n' + 'sum')
        self.runflow.moveCursor(QTextCursor.End)


class MainApplication(QMainWindow):

    def __init__(self):

        QMainWindow.__init__(self)
        self.setWindowTitle('Home')
        self.setGeometry(50, 50, 500, 500)

        #Main widget
        self.mainwidget = QWidget()
        self.mainlayout = QVBoxLayout()

        #Widgets
        #Form line edits
        self.no1 = QLineEdit()
        self.no2 = QLineEdit()

        self.run = QPushButton('Run')
        self.exit = QPushButton('Exit')

        self.form = QFormLayout()
        self.form.addRow('First number', self.no1)
        self.form.addRow('Second number', self.no2)

        self.mainlayout.addLayout(self.form)
        self.mainlayout.addWidget(self.run)
        self.mainlayout.addWidget(self.exit)

        self.exit.clicked.connect(self.exitapplication)
        self.run.clicked.connect(self.mainprogramrun)

        self.mainwidget.setLayout(self.mainlayout)
        self.mainwidget.show()

    def exitapplication(self):
        sys.exit()

    def mainprogramrun(self):

        number1 = float(self.no1.text())
        number2 = float(self.no2.text())

        run = GeneralizedRun(number1, number2)
        run.initUi(self)


def main():

    application = QApplication(sys.argv)
    application_window = MainApplication()
    application.exec_() 

if __name__ == '__main__':
    main()

Upvotes: 1

Views: 59

Answers (1)

ekhumoro
ekhumoro

Reputation: 120598

The example code won't work correctly because you are not keeping a reference to the GeneralizedRun window. So the first thing to fix is this:

class MainApplication(QMainWindow):
    ...

    def mainprogramrun(self):

        number1 = float(self.no1.text())
        number2 = float(self.no2.text())

        # keep a reference to the window
        self.runner = GeneralizedRun(number1, number2)
        self.runner.initUi(self)

To pass the sum back to the gui, the thread class should look like this:

class AreaThread(QThread):
    # re-define the signal to send a value
    signal = pyqtSignal(float)

    def __init__(self, no1, no2, parent):
        QThread.__init__(self)

        self.no1 = no1
        self.no2 = no2

    def area(self):
        for i in range(10):
            self.sum = self.no1 + self.no2
            self.no1 = self.no2
            self.no2 = self.sum
            # pass the value
            self.signalemit(self.sum)
            time.sleep(1)

    def signalemit(self, value):
        # send the value
        self.signal.emit(value)

    def run(self):
        self.area()

and the signal handler should look like this:

class GeneralizedRun (QMainWindow):
    ...

    def updatetexteditor(self, value):
        # show the value
        self.runflow.insertPlainText('\n\nsum: %s' % value)
        self.runflow.moveCursor(QTextCursor.End)

Upvotes: 1

Related Questions