我刚开始使用pyqt,我想从按钮更改图标。 但是我把它从另一个类中删除而pyqt不喜欢它。
错误是:QPixmap:在GUI线程之外使用pixmaps是不安全的
我知道我必须使用singal en emits。 但我不知道如何使用它从按钮更改图标。
现在我的代码:
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()
答案 0 :(得分: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_())