python Qlabel text is not updated as I expect

41 Views Asked by At

I have a question about Qlabel. Following is the example of code. While opertaiong the program, I want to show message that the system is operating. But somehow Qlabel message was not updated as I expected. “self.text_label.setText('reading file ......') “ area of following code. (this is not shown as expected)

And at the end Qlabel text was updated. “self.text_label.setText('opertaion finish') “ area
(this is shown as expected)

If there is any mistake or missing information, please advise.

import  os , sys, time
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (QMainWindow, QVBoxLayout,QHBoxLayout,
     QApplication,QPushButton,QWidget,QRadioButton,QLabel,QTextEdit)  
class Main(QMainWindow):
    def __init__(self):
        super().__init__()

        #overall layout
        layout = QVBoxLayout()
                
        # Pushbutton for excution         
        bt_layout = QtWidgets.QGridLayout()
        bt_layout.setContentsMargins(0,0,0,20)
        start_bt = QPushButton("start")
        start_bt.setStyleSheet("background-color:lightblue")        
        bt_layout.addWidget(start_bt)
        start_bt.clicked.connect(self.start)
        layout.addLayout(bt_layout)
 
        text_layout = QHBoxLayout()
        self.text_label = QLabel()
        self.text_label.setText('before operation') 
        text_layout.addWidget(self.text_label)                    
        layout.addLayout(text_layout)

        #overall layout        
        self.container = QWidget()
        self.container.setLayout(layout)
        self.setCentralWidget(self.container)               
        self.setGeometry(500, 100, 330, 200)
        self.show()
    
    def start(self):
        self.text_label.setText('reading file ......')   
        time.sleep(5)
            
        self.text_label.setText('opertaion finish')   
        self.text_label.setStyleSheet("background-color:#00FF00 ")        
        
# call the main() function.
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Main()
    sys.exit(app.exec_())
1

There are 1 best solutions below

2
Alexander On BEST ANSWER

If all you want is to for the label to update in real time then you can use QTimer and it's singleShot class method to trigger the update once the pre-set amount of time has completely elapsed.

For example you can call the QTimer.singleShot in your start method just after setting the label text to "reading file.......", and set the callback to another method that performs the rest of the label updates after 5 seconds.

...
from PyQt5 import QtCore
...

...
...

    def start(self):
        self.text_label.setText('reading file ......')
        QtCore.QTimer().singleShot(5000, self.updateLabel)

    def updateLabel(self):
        self.text_label.setText('operation finish')
        self.text_label.setStyleSheet("background-color:#00FF00 ")

This won't be of much help though if you actually are going to be opening a file that takes 5 seconds to read. If this is the case then you will likely want to perform that operation in a different thread and then pass the read data from the thread once it has finished reading it by connecting to a signal that sends the read data when it emits.

For example:


class ReadThread(QThread):
    fileRead = Signal(str)

    def __init__(self, filename):
        super().__init__()
        self.filename = filename

    def run(self):
        with open(self.filename) as file:
            data = file.read()
        self.fileRead.emit(data)
        

class Main(QMainWindow):
    def __init__(self):
        super().__init__()
        ...
        ...

    def updateLabel(self, data):
        ... do something with data
        self.text_label.setText('operation finish')
        self.text_label.setStyleSheet("background-color:#00FF00 ")


    def start(self):
        self.text_label.setText('reading file ......')
        self.thread = ReadThread(filename)
        self.thread.fileRead.connect(self.updateLabel)
        self.thread.finished.connect(self.thread.deleteLater())
        self.thread.start()