假设我有一个带有三个控件的简单窗口:一个组合框、一个push(切换)按钮和一个文本编辑控件。为了增加趣味,我需要在线程中运行算法(当按下切换键时),但我想解决主要问题的方法不会受到
的影响。当切换按钮被按下时,我想读取当前的ComboBox值并更新TextEdit的值。
这是我尝试过的方法,但没有成功。也许这是一个愚蠢的错误,或者我应该改变设计(QML会帮助使这更容易一点吗?):
#!/usr/bin/env python
import sys
import threading
try:
from PySide import QtGui
from PySide import QtCore
except:
from PyQt4.QtCore import pyqtSlot as Slot
from PyQt4 import QtGui
from PyQt4 import QtCore
class MyUI(QtGui.QWidget):
def __init__(self):
super(MyUI, self).__init__()
self.initUI()
def initUI(self):
someValues = [1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200]
self.setGeometry(100, 300, 640, 450) #window's geometry
lblValueChoice = QtGui.QLabel(self)
lblValueChoice.setGeometry(10, 10, (self.width() - 20), 27)
lblValueChoice.setText("Select your value:")
cmbValueChoice = QtGui.QComboBox(self)
cmbValueChoice.setObjectName("valueChoice")
cmbValueChoice.setGeometry(10, (lblValueChoice.y() + lblValueChoice.height() + 5), (self.width() - 20), 27)
for item in someValues: cmbSerialPorts.addItem(item)
cmbSerialPorts.setCurrentIndex(len(someValues)-1)
pbStartReading = QtGui.QPushButton("Start doing the magic!", self)
pbStartReading.setGeometry(10, (cmbValueChoice.y() + cmbValueChoice.height() + 10), (self.width() - 20), 27)
pbStartReading.setCheckable(True)
pbStartReading.clicked[bool].connect(lambda: self.startReading(bool, str(cmbValueChoice.currentText())))
textEdit = QtGui.QTextEdit(self)
textEdit.setObjectName("textEdit")
textEdit.setGeometry(10, (pbStartReading.y() + pbStartReading.height() + 10), (self.width() - 20), (self.height() - (pbStartReading.y() + pbStartReading.height() + 10) - 10) )
textEdit.append(add_env())
self.setWindowTitle(u'MyMiserableUIFailure')
self.show()
def startReading(self, bool, myvalue):
threading.Thread(target=self.readingLoop, args=(bool, myvalue, )).start()
def readingLoop(self, bool, myvalue):
while bool:
# the error happens in the line below, when I
# try to reference the textEdit control
# -------------------------------------------
textEdit.append("this actually works!n")
def main():
app = QtGui.QApplication(sys.argv)
theui = MyUI()
sys.exit(app.exec_())
def add_env():
newLine = QtCore.QString("n")
env_info = "The system is:" + newLine
env_info += newLine + "System/OS name: " + str(platform.system())
env_info += newLine + "System release: " + str(platform.release())
env_info += newLine + "System release version: " + str(platform.version())
env_info += newLine + "Machine type: " + str(platform.machine())
env_info += newLine + "Platform: " + str(platform.platform(aliased=0, terse=1))
env_info += newLine + "Processor: " + str(platform.processor())
env_info += newLine + "Network name: " + str(platform.node())
env_info += newLine + "Python ver(maj,min,patch): " + str(platform.python_version_tuple())
env_info += newLine + "Python build: " + str(platform.python_build())
env_info += newLine + "Python implementation: " + str(platform.python_implementation())
env_info += newLine
env_info += newLine + "***************************"
return env_info
if __name__ == '__main__':
main()
你不能直接引用来自其他线程的ui元素。你应该使用信号。我在你的代码中改变了它,见下面。我没有测试它,但这是应该这样做的。
#!/usr/bin/env python
import sys
import threading
try:
from PySide import QtGui
from PySide import QtCore
from PySide.QtCore import Signal
except:
from PyQt4.QtCore import pyqtSignal as Signal
from PyQt4 import QtGui
from PyQt4 import QtCore
class MyUI(QtGui.QWidget):
# Add Signal
text_edit_evt = Signal(str)
def __init__(self):
super(MyUI, self).__init__()
self.initUI()
# Connect the signal
self.text_edit_evt.connect(self.textEdit.append)
def initUI(self):
someValues = [1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200]
self.setGeometry(100, 300, 640, 450) #window's geometry
lblValueChoice = QtGui.QLabel(self)
lblValueChoice.setGeometry(10, 10, (self.width() - 20), 27)
lblValueChoice.setText("Select your value:")
cmbValueChoice = QtGui.QComboBox(self)
cmbValueChoice.setObjectName("valueChoice")
cmbValueChoice.setGeometry(10, (lblValueChoice.y() + lblValueChoice.height() + 5), (self.width() - 20), 27)
for item in someValues: cmbSerialPorts.addItem(item)
cmbSerialPorts.setCurrentIndex(len(someValues)-1)
pbStartReading = QtGui.QPushButton("Start doing the magic!", self)
pbStartReading.setGeometry(10, (cmbValueChoice.y() + cmbValueChoice.height() + 10), (self.width() - 20), 27)
pbStartReading.setCheckable(True)
pbStartReading.clicked[bool].connect(lambda: self.startReading(bool, str(cmbValueChoice.currentText())))
# Use self.textEdit so it can be referenced from other functions
self.textEdit = QtGui.QTextEdit(self)
self.textEdit.setObjectName("textEdit")
self.textEdit.setGeometry(10, (pbStartReading.y() + pbStartReading.height() + 10), (self.width() - 20), (self.height() - (pbStartReading.y() + pbStartReading.height() + 10) - 10) )
self.textEdit.append(add_env())
self.setWindowTitle(u'MyMiserableUIFailure')
self.show()
def startReading(self, bool, myvalue):
threading.Thread(target=self.readingLoop, args=(bool, myvalue, )).start()
def readingLoop(self, bool, myvalue):
while bool:
# the error happens in the line below, when I
# try to reference the textEdit control
# -------------------------------------------
# Emit the Signal we created
self.text_edit_evt.emit("this actually works!n")
def main():
app = QtGui.QApplication(sys.argv)
theui = MyUI()
sys.exit(app.exec_())
def add_env():
newLine = QtCore.QString("n")
env_info = "The system is:" + newLine
env_info += newLine + "System/OS name: " + str(platform.system())
env_info += newLine + "System release: " + str(platform.release())
env_info += newLine + "System release version: " + str(platform.version())
env_info += newLine + "Machine type: " + str(platform.machine())
env_info += newLine + "Platform: " + str(platform.platform(aliased=0, terse=1))
env_info += newLine + "Processor: " + str(platform.processor())
env_info += newLine + "Network name: " + str(platform.node())
env_info += newLine + "Python ver(maj,min,patch): " + str(platform.python_version_tuple())
env_info += newLine + "Python build: " + str(platform.python_build())
env_info += newLine + "Python implementation: " + str(platform.python_implementation())
env_info += newLine
env_info += newLine + "***************************"
return env_info
if __name__ == '__main__':
main()