Search code examples
pythonpyqt4qthread

how to send a value from one class to another using pyqt4 and python


i'm having some trouble in building my app, I have a GUI made in pyqt4 and Python, I use QThread to check the cpu load every 2 seconds and I want to diplay it on a progress bar. My GUI is in one class and my Qthread is in the other.

This is my code: pyqt classes, my code printscreen

I want to know how to pass my values collected in QThread to Qobjects in my other Class.

import sys,os,module,config_read,time,threading,datecs_print,mysql.connector as mariadb,commandList
import psutil,logging
from PyQt4 import QtGui, uic ,QtSql,QtCore
from PyQt4.QtCore import QThread, SIGNAL
import resources
import webbrowser
sys.stderr = open("errlog.txt", "w")

class systemValues(QThread):
    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def cpuRunValue(self):
        while (1):
            for x in range(2):
                p = psutil.cpu_percent(1,False)
                return p

    def cpuProgressBarUpdate(self):
        while(1):
            # MyWindow.setcpuBarValue(val=77)
            MyWindow.cpuBar.setValue(value=77)

    def run(self):
        # self.cpuRunValue()
        print(self.cpuRunValue())
       # self.cpuProgressBarUpdate()

class MyWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QDialog.__init__(self)
        super(MyWindow, self).__init__()
        file_path = os.path.abspath("ui/sales_window.ui")
        uic.loadUi(file_path, self)
        self.myThread = systemValues()
        self.myThread.start()

    def setcpuBarValue(self):
        threading.Thread(target=self.cpuBar.setValue(systemValues.cpuRunValue())).start()

This is my code, I get no error. I just cant transfer my value I get from cpuRunValue() to QprogressBar from MyWindow. I'm not very experienced with this.

PS: I eliminated lots of code that's not necessary, but please let me know if you need more info. Thank You.


Solution

  • If you want to use threads in Qt then you must understand them well. For instance read this page first. Certainly don't mix the QThread with the threading package from the Python standard library.

    I hope you're not offended if I think that your probably fairly new to programming. I advise you to not use threads (in general and in Qt) until you have more experience. Threads are hard to use correctly, even for seasoned programmers, and therefore should only be used if necessary. For this reason the Qt documentation on threads even includes a section about alternatives.

    You want to execute a function every 2 seconds, so in your case the best solution is to use a QTimer and connect its timeout signal to a slot that updates the progress bar. Like so:

    #!/usr/bin/env python
    
    import sys
    import psutil
    from PyQt5 import QtCore, QtWidgets
    
    class MyWidget(QtWidgets.QWidget):
    
        def __init__(self, parent=None):
    
            super().__init__(parent=parent)
    
            self.layout = QtWidgets.QVBoxLayout()
            self.setLayout(self.layout)
    
            self.progressBar = QtWidgets.QProgressBar()
            self.layout.addWidget(self.progressBar)
    
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.updateCpu)
            self.timer.start(100) # Every 0.1 seconds
    
        def updateCpu(self):
            cpu = psutil.cpu_percent(None, False)
            #print("cpu = {}%".format(cpu))
            self.progressBar.setValue(cpu)
    
    
    def main():
        app = QtWidgets.QApplication(sys.argv)
    
        win = MyWidget()
        win.show()
        win.raise_()
        app.exec_()
    
    if __name__ == "__main__":
        main()
    

    Note that I changed the first parameter of cpu_percent to None. This makes the call return immediately instead of lasting one second (and therefore you can update the progress bar more often if you want). Setting it to None causes the first call of cpu_percent to return a meaningless value, but in your cause that's not an issue I think. See the documention.

    Finally, even though you removed a lot of unnecessary code, your code example was not yet minimal (e.g. the import datecs_print is not necessary to run it, and I don't have this module). I was also not complete (e.g. the "ui/sales_window.ui" file was missing so I couldn't run it). Please read the page on how to make an MCVE. You will get a lot more help next time if you include a small program that we can just copy-paste-execute.

    Hope this helps