Search code examples
pythonmultithreadingpyqtpyqt4

Change Button Color in Qt Thread Python


I need to change the color of QPushButton, but an error occurred: "AttributeError: type object 'ProyectoTFM' has no attribute 'ui'". I don't know hoy to acced to a ui variable from my thread. This is my code:

import sys
import OpenOPC
import time
import threading

from proyectoQt import *


def actualizarDatosOPC():
    while 1:
        time.sleep(5)
        if(itemsOPC[15])[1]!=0:
            #Error on next line
            ProyectoTFM.ui.AP08Button.setStyleSheet("background-color: red")
    return


class ProyectoTFM(QtGui.QMainWindow):
    def __init__(self,parent=None):
        QtGui.QMainWindow.__init__(self,parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.startTheThread()
        print('Init')

    def startTheThread(self):
        threadQt = threading.Thread(target = actualizarDatosOPC)
        threadQt.start()


def clienteOPC():
    opc=OpenOPC.client()
    opc.connect('Kepware.KEPServerEX.V6')

    global itemsOPC

    while 1:
        itemsOPC = opc.read(opc.list('PLC.PLC.TAGS'))
        time.sleep(5)
    return

threads = list()
threadOPC = threading.Thread(target=clienteOPC)
threads.append(threadOPC)
threadOPC.start()
time.sleep(5)


if __name__== "__main__":
    app=QtGui.QApplication(sys.argv)
    myapp = ProyectoTFM()
    myapp.show()
    sys.exit(app.exec_())
    threadOPC.__delete()

Sorry for my English and thanks.


Solution

  • It is not correct to modify the view from a different thread to the main one, a way to solve the problem without using QThread is to create a signal that connects to some slot that changes the color of the button. To be able to emit the signal from the new thread we must pass the object to him through the parameter args.

    def actualizarDatosOPC(obj):
        while 1:
            time.sleep(5)
            if(itemsOPC[15])[1]!=0:
                #Error on next line
                obj.sendChangeColor.emit()
        return
    
    
    class ProyectoTFM(QtGui.QMainWindow):
        sendChangeColor = QtCore.pyqtSignal()
        def __init__(self,parent=None):
            QtGui.QMainWindow.__init__(self,parent)
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
            self.startTheThread()
            print('Init')
            self.sendChangeColor.connect(lambda: self.ui.AP08Button.setStyleSheet("background-color: red"))
    
        def startTheThread(self):
            threadQt = threading.Thread(target = actualizarDatosOPC, args=(self,))
            threadQt.start()