Search code examples
python-3.xpyqtpyqt5pysidepyside6

Outputting text in a form with flow using signals


Need help with the following task:

There is a main window MainWindow and there is a separate class of a stream in which there is a text. Tell me how to use signals on the plainTextEdit form, which is located on the main form, to display text through signals?

Main window code:

import sys

from PySide6.QtWidgets import *

from Controller.Potok_Controller import Potok_Controller
from View.ui_potok import Ui_MainWindow

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

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.pushButton.clicked.connect(self.open_window)

    def open_window(self):
        self.myThread = Potok_Controller()
        # self.myThread.mysignal.connect(self.sendText)
        self.myThread.start()

if __name__ == '__main__':
    app = QApplication()
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

UI code of the main window:

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

################################################################################
## Form generated from reading UI file 'untitledkonQbZ.ui'
##
## Created by: Qt User Interface Compiler version 6.3.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QFrame, QMainWindow, QPlainTextEdit,
    QPushButton, QSizePolicy, QVBoxLayout, QWidget)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.frame = QFrame(self.centralwidget)
        self.frame.setObjectName(u"frame")
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.verticalLayout_2 = QVBoxLayout(self.frame)
        self.verticalLayout_2.setObjectName(u"verticalLayout_2")
        self.plainTextEdit = QPlainTextEdit(self.frame)
        self.plainTextEdit.setObjectName(u"plainTextEdit")

        self.verticalLayout_2.addWidget(self.plainTextEdit)


        self.verticalLayout.addWidget(self.frame)

        self.frame_2 = QFrame(self.centralwidget)
        self.frame_2.setObjectName(u"frame_2")
        self.frame_2.setFrameShape(QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QFrame.Raised)
        self.verticalLayout_3 = QVBoxLayout(self.frame_2)
        self.verticalLayout_3.setObjectName(u"verticalLayout_3")
        self.pushButton = QPushButton(self.frame_2)
        self.pushButton.setObjectName(u"pushButton")

        self.verticalLayout_3.addWidget(self.pushButton)


        self.verticalLayout.addWidget(self.frame_2)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"\u0421\u0442\u0430\u0440\u0442 \u043f\u043e\u0442\u043e\u043a\u0430", None))
    # retranslateUi

Thread class code:

import time

from PySide6.QtCore import QThread

class Potok_Controller(QThread):
    def __init__(self, parent=None):
        super(Potok_Controller, self).__init__(parent)

    def txt(self):
        txt1 = 'test1'
        time.sleep(1)
        txt2 = 'test2'
        time.sleep(1)
        txt3 = 'test3'

    def run(self):
        self.txt()

Solution

  • You just need to implement the sendtext method that you have commented out in your open_window method, and then create a signal that accepts a string parameter in your Potok_Controller class and emit the signal from the threads run method.

    For Example:

    class Potok_Controller(QThread):
        
        mysignal = Signal([str])   # create signal
    
        def __init__(self, parent=None):
            super(Potok_Controller, self).__init__(parent)
    
        def txt(self):
            txt1 = 'test1'
            time.sleep(1)
            txt2 = 'test2'
            time.sleep(1)
            txt3 = 'test3'
            return txt1 + txt2 + txt3 
    
        def run(self):
            self.mysignal.emit(self.txt())  # emit the signal with text as parameter
    
    class MainWindow(QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            self.ui.pushButton.clicked.connect(self.open_window)
    
        def sendText(self, text):  # create the sendText method
            self.ui.plaintextedit.setPlainText(text)
    
        def open_window(self):
            self.myThread = Potok_Controller()
            self.myThread.mysignal.connect(self.sendText)  # uncomment this
            self.myThread.start()