2013-08-22 50 views
0

我刚刚开始使用pyqt,我想从按钮更改图标。 但是我从另一个课堂上抨击它,pyqt不喜欢那样。Pyqt:从按钮更改图标

的错误是:的QPixmap:是不是安全使用GUI线程

我知道我必须用葛带外发射像素图。 但我不知道如何使用它来改变按钮的图标。

这是我现在的代码:

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:[email protected]/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:[email protected]/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() 

回答

1

不能从除主界面线程以外的任何其他线程触及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_()) 
+0

它不起作用。 Python说没有属性Signal? – Stijnb

+0

@Stijnb你是否尝试过我发布的完全相同的代码?如果是,您正在使用哪个版本的PyQt4? –

+0

我已经安装了本周。我想我有最新的版本。 – Stijnb