2013-05-12 41 views
0

假设我有一个带有三个控件的简单窗口:一个组合框,一个推动(切换)按钮和一个文本编辑控件。 为了让它更具吸引力,我需要算法运行在一个线程中(同时按下切换按钮),但是我认为解决主要问题的方法不会受到影响如何从代码中引用PyQt UI元素?

当切换按钮是按下,我想读取当前的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() 

回答

0

你不能直接从一个不同的线程参考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() 
+0

我得到误差加法信号线:线22,在MyUI text_edit_evt = QtCore.SIGNAL(STR) 类型错误:SIGNAL(STR):参数1具有意想不到类型的 'type' 如果我尝试使用“”更改str,然后我得到: line 28,in __init__ self.text_edit_evt.connect(self.textEdit.append) AttributeError:'str'object has no attribute'connect' – user2374792 2013-05-12 12:48:41

+0

显然PyQt4有QtCore.pyqtSignal而不是QtCore.Signal。我更新了代码以使用PySide和PyQt4。 – BrtH 2013-05-12 14:03:00

+0

谢谢!另外一个未来,对不起:) 现在线应该连接信号似乎没有找到文字编辑:self.text_edit_evt.connect(self.textEdit.append) 这是它引发错误: 线30,在__init__ 自我.text_edit_evt.connect(self.textEdit.append) AttributeError:'MyUI'对象没有'textEdit'属性' – user2374792 2013-05-12 15:06:59