0

假设我有一个包含三个控件的简单窗口:一个组合框、一个推动(切换)按钮和一个文本编辑控件。为了给它增添趣味,我需要算法在线程中运行(按下切换按钮时),但我想我的主要问题的解决方案不会受到影响

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

1 回答 1

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()
于 2013-05-12T12:30:31.910 回答