从线程中向PyQt的lineEdit引入文本

1 投票
2 回答
2193 浏览
提问于 2025-04-18 10:05

我想知道怎么在一个线程中给一个文本框(lineEdit)添加文字,而不会让程序崩溃。关键的代码在“fil”这个类里,主要是这行:Principal.self.aplicacio.actual_lineEdit.setText(self.temp)

    # !/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import serial
import threading
from time import sleep
from PyQt4 import QtCore, QtGui
from temperaturaUI import Ui_Form


class Principal(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        self.aplicacio = Ui_Form()
        self.aplicacio.setupUi(self)

        self.aplicacio.sortir_Button.clicked.connect(exit)

        self.aplicacio.connectar_Button.clicked.connect(self.connectar)

    def connectar(self):
        try:
            arduino = serial.Serial('/dev/ttyACM0', 9600)
            print "Connectat amb èxit"
            temperatura = fil(0, arduino, self.aplicacio.actual_lineEdit)
            temperatura.start()
        except:
            print "Impossible connectar a l'Arduino"


class fil(threading.Thread):
    def __init__(self, temp, serie, line):
        threading.Thread.__init__(self)
        self.temp = temp
        self.serie = serie
        self.line = line

    def run(self):
        try:
            while 1:
                self.temp = self.serie.readline()
                if self.temp != 0:
                     **Principal.self.aplicacio.actual_lineEdit.setText(self.temp)**
                sleep(0.2)
        except:
            print "Error al llegir de l'Arduino"



def main():
    app = QtGui.QApplication(sys.argv)
    aplicacio = Principal()
    aplicacio.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

2 个回答

0

有几种正确的方法可以做到这一点。

第一种方法是使用 QThread,而不是 Python 的线程。这样你就可以用 Qt 的信号把消息从 fil 线程传回 Qt 的主线程,然后把这个消息添加到 QLineEdit 中。还有一种类似的方法是继续使用 Python 的线程,但把你的消息放在一个 Python 的 Queue.Queue() 对象里。然后,一个额外的 QThread 会读取这个 Queue,它的唯一目的就是从 Queue 中读取消息,并向主线程发出信号。

这两种方法的共同点是,你只在主线程中访问 Qt 的 GUI 对象,并使用信号和槽来实现线程之间的通信。这里有一些其他问题,我也回答过类似的问题(你可以根据自己的程序进行调整):

不过,自从回答这些问题以来,我和我的同事们创建了一个项目,旨在简化编写多线程 Qt 应用程序的过程。这个项目叫做 qtutils,可以在 PyPi 上找到,所以你可以用 pip 或 easy_install 安装它(只需在命令行/终端窗口中运行 pip install qtutilseasy_install qtutils)。

这个库有一些功能,比如 inmaininmain_later,可以在 Qt 的主线程中运行指定的方法(无论是从哪个线程调用)同步或异步。关于如何使用这些方法的文档可以在 这里找到。我已经修改了你的示例代码,使用了我的 inmain 方法,并把代码放在这里:http://pastebin.com/QM1Y6zBx——显然,你需要安装 qtutils 才能让它工作!

0

你可以使用signals。你需要在fil这个类里添加一个信号,用来发出新的文本:

class fil(threading.Thread):
    update_line_edit = pyqtSignal(str)
    def __init__(self, temp, serie, line):
        ...

    def run(self):
        try:
            while True:
                self.temp = self.serie.readline()
                if not self.temp:
                    update_line_edit.emit(self.temp)
        ...

然后,只需将这个信号连接到你Principal类中的一个slot函数:

class Principal(QtGui.QWidget):
    def __init__(self):
        ...

    def connectar(self):
        try:
            arduino = serial.Serial('/dev/ttyACM0', 9600)
            print "Connectat amb èxit"
            temperatura = fil(0, arduino, self.aplicacio.actual_lineEdit)
            temperatura.change_line_edit.connect(self.update_line_edit)
        ...

    def update_line_edit(self, text):
        self.aplicacio.actual_lineEdit.setText(text)

撰写回答