0

我刚开始使用 pyqt,我想从按钮更改图标。但我正在从另一个类中删除它,而 pyqt 不喜欢那样。

错误是:QPixmap:在 GUI 线程之外使用像素图是不安全的

我知道我必须使用信号 en 发射。但我不知道我必须如何使用它来更改按钮的图标。

这是我现在的代码:

import sys
import time
from PyQt4 import QtGui, QtCore
from pymodbus.exceptions import ConnectionException
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from data.database import Tags, Query_Tags


class Example(QtGui.QMainWindow):

    def __init__(self):
        super(Example, self).__init__()

        self.db_engine = create_engine('mysql://modbususer:modbususer@localhost/modbus')

        self.db_session = sessionmaker(bind=self.db_engine)
        self.db_session = self.db_session()  

        self.status = 0
        self.initUI()

    def initUI(self):               

        self.button = QtGui.QPushButton('Aan', self)
        self.button.clicked.connect(self.run)     
        self.button.move(50,50)


        Uit = QtGui.QPushButton('Uit', self)
        Uit.clicked.connect(self.off)     
        Uit.move(150,50)

        self.setGeometry(300, 300, 500, 150)
        self.setWindowTitle('Quit button')    
        self.show()

        self.worker = WorkThread(self)
        self.worker.start()

    def run(self):

        add_tag = Query_Tags('18', '1')
        self.db_session.add(add_tag)
        self.db_session.commit()


    def off(self):

        add_tag = Query_Tags('18', '0')
        self.db_session.add(add_tag)
        self.db_session.commit()

        self.status = 0

        print self.store

    def change(self):

        print "test"
        #self.button.setIcon(QtGui.QIcon("/home/stijnb/test/icon.png"))
        #self.button.setIconSize(QtCore.QSize(16,16))

    def database(self, store):

        self.store = store

"""
    Thread
"""
class WorkThread(QtCore.QThread):

    def __init__(self, layout):

        QtCore.QThread.__init__(self)

        self.layout = layout

    def __del__(self):
        self.wait()

    def run(self):

        self.database = {}

        while True:

            self.db_engine = create_engine('mysql://modbususer:modbususer@localhost/modbus')

            self.db_session = sessionmaker(bind=self.db_engine)
            self.db_session = self.db_session() 

            for result in self.db_session.query(Tags):

                self.database[int(result.id)] = {'naam': result.name, 'value': result.value}

            self.change_icons()
            time.sleep(1)

        return 

        self.terminate()

    def change_icons(self):

        print self.database[21]['value']

        if self.database[21]['value'] == '1':

            self.layout.button.setIcon(QtGui.QIcon("/home/stijnb/test/aan.png"))
            self.layout.button.setIconSize(QtCore.QSize(16,16))

        else:

            self.layout.button.setIcon(QtGui.QIcon("/home/stijnb/test/uit.png"))
            self.layout.button.setIconSize(QtCore.QSize(16,16))

def main():

    app = QtGui.QApplication(sys.argv)

    ex = Example()

    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
4

1 回答 1

1

您不能从除主 GUI 线程之外的任何其他线程触摸 GUI 元素。这就是 Qt 引入消息传递(信号和插槽)的原因。您可以连接到来自工作线程的信号,该信号将在主线程中捕获,然后在主线程中您可以更改您想要的任何元素。

这是一个非常简单的示例,我在其中演示了该概念。

import sys
from PyQt4 import QtGui, QtCore

class Example(QtGui.QMainWindow):
    def __init__(self):
        super(Example, self).__init__()
        # Create a button and set it as a central widget
        self.button = QtGui.QPushButton('My Button', self)
        self.setCentralWidget(self.button)
        # Start the thread
        self.worker = WorkThread(self)
        self.worker.start()
        # Connect the thread's signal "change_text" to
        # "self.change_thread" function
        self.worker.change_text.connect(self.change_text)

    def change_text(self):
        # Slots are always executed in the GUI thread so it's safe to change
        # anything you want in a slot function. Here we just flip the button
        # text from foo to bar and back. But you can change the image or do
        # whatever you want.
        # Slots can also receive parameters so you can emit from your thread
        # which text should be set
        self.button.setText('bar' if self.button.text() == 'foo' else 'foo')


class WorkThread(QtCore.QThread):
    # Define the signal
    change_text = QtCore.pyqtSignal()

    def __init__(self, layout):
        QtCore.QThread.__init__(self)

    def run(self):
        while True:
            # emit the signal every 3 seconds
            self.sleep(3)
            self.change_text.emit()


app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
于 2013-08-22T15:04:45.960 回答