PyQt5中点击AI按钮如何将外部Python脚本输出设置到LineEdit
问题描述
我开发了一个基于AI的PyQt5程序,已查阅StackOverflow上所有关于PyQt设置文本的帖子,希望点击Auto(AI)按钮时,将字符串设置到lineEdit控件中。
当前按钮点击事件代码如下:
def AI_click(self): #self.lineEdit.setText("YO") os.system('python detect_video.py --weights ./checkpoints/custom-416 --size 416 --model yolov4 --video 0 --plate') #self.lineEdit.setText(line1)
本质上,AI按钮会执行Python脚本并输出字符串,我想知道如何在GUI文件中获取另一个.py文件的输出字符串。目前程序执行脚本后,无法执行self.lineEdit.setText(line1)来设置文本,也无法获取该字符串。完整代码如下:
class Ui_Dialog(object): def setupUi(self, Dialog,var): Dialog.setObjectName("Dialog") Dialog.resize(1120, 850) Dialog.setStyleSheet("QDialog#Dialog{\n""background-color: qlineargradient(spread:pad,x1:0.0113636, y1:0.966, x2:1, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))\n" "\n" "}\n" "\n" "") self.widget = QtWidgets.QWidget(Dialog) self.widget.setGeometry(QtCore.QRect(0, 0, 201, 851)) self.widget.setStyleSheet("\n" "background-color: rgb(100, 100, 100);") self.widget.setObjectName("widget") self.dashboardButton = QtWidgets.QPushButton(self.widget) self.dashboardButton.setGeometry(QtCore.QRect(0, 250, 201, 51)) self.dashboardButton.setStyleSheet("QPushButton {\n" " background-color: rgb(255, 255, 255);\n" " color: #FFFFFF;\n" " \n" " padding: 2px;\n" " font: bold 20px; color:black;\n" " \n" " \n" " }\n" "QPushButton:hover {\n" " background-color: rgb(98, 98, 98);\n" "}") self.dashboardButton.setObjectName("dashboardButton") self.dashboardButton_2 = QtWidgets.QPushButton(self.widget) self.dashboardButton_2.setGeometry(QtCore.QRect(0, 370, 201, 51)) self.dashboardButton_2.setStyleSheet("QPushButton {\n" " background-color: rgb(255, 255, 255);\n" " color: #FFFFFF;\n" " \n" " padding: 2px;\n" " font: bold 20px; color:black;\n" " \n" " \n" " }\n" "QPushButton:hover {\n" " background-color: rgb(98, 98, 98);\n" "}") self.dashboardButton_2.setObjectName("dashboardButton_2") self.label = QtWidgets.QLabel(Dialog) self.label.setGeometry(QtCore.QRect(250, 20, 171, 91)) self.label.setStyleSheet("font-size: 30px;\n" "font: bold;\n" "") self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(Dialog) self.label_2.setGeometry(QtCore.QRect(630, 70, 416, 416)) self.label_2.setText("") self.label_2.setPixmap(QtGui.QPixmap("D:/Downloads/numplate.jpg")) self.label_2.setScaledContents(True) self.label_2.setObjectName("label_2") self.label_3 = QtWidgets.QLabel(Dialog) self.label_3.setGeometry(QtCore.QRect(640, 530, 401, 241)) self.label_3.setText("") self.label_3.setPixmap(QtGui.QPixmap("D:/Downloads/20886263.jpg")) self.label_3.setScaledContents(True) self.label_3.setObjectName("label_3") self.lineEdit = QtWidgets.QLineEdit(Dialog) #self.lineEdit.setText("YO") # if string!=None: # print("called") # print(string) # self.lineEdit.setText(string) self.lineEdit.setGeometry(QtCore.QRect(300, 280, 221, 41)) self.lineEdit.setObjectName("lineEdit") self.lineEdit_2 = QtWidgets.QLineEdit(Dialog) self.lineEdit_2.setGeometry(QtCore.QRect(300, 360, 221, 41)) self.lineEdit_2.setObjectName("lineEdit_2") self.label_4 = QtWidgets.QLabel(Dialog) self.label_4.setGeometry(QtCore.QRect(300, 260, 81, 16)) self.label_4.setObjectName("label_4") self.label_5 = QtWidgets.QLabel(Dialog) self.label_5.setGeometry(QtCore.QRect(300, 340, 81, 16)) self.label_5.setObjectName("label_5") self.pushButton = QtWidgets.QPushButton(Dialog) self.pushButton.setGeometry(QtCore.QRect(420, 430, 101, 31)) self.pushButton.setObjectName("pushButton") self.pushButton_AI = QtWidgets.QPushButton(Dialog) self.pushButton_AI.setGeometry(QtCore.QRect(300, 430, 101, 31)) self.pushButton_AI.setObjectName("pushButton_AI") print("car:"+var) self.pushButton.clicked.connect(self.clickme) self.pushButton_AI.clicked.connect(self.AI_click) lineEdit= self.lineEdit self.retranslateUi(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog) def AI_click(self): #self.lineEdit.setText("YO") os.system('python detect_video.py --weights ./checkpoints/custom-416 --size 416 --model yolov4 --video 0 --plate') #self.lineEdit.setText(line1) def clickme(self): np=self.lineEdit.text() cnic=self.lineEdit_2.text() table_data(np,cnic) # printing pressed print(np+cnic) def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "Dialog")) self.dashboardButton.setText(_translate("Dialog", "Dashboard")) self.dashboardButton_2.setText(_translate("Dialog", "Record")) self.label.setText(_translate("Dialog", "Dashboard")) self.label_4.setText(_translate("Dialog", "Number Plate:")) self.label_5.setText(_translate("Dialog", "CNIC:")) self.pushButton.setText(_translate("Dialog", "Save ")) self.pushButton_AI.setText(_translate("Dialog", "Auto")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) Dialog = QtWidgets.QDialog() ui = Ui_Dialog() var="" ui.setupUi(Dialog,var) Dialog.show() sys.exit(app.exec_())
解决方案
os.system仅能返回脚本执行的状态码,无法捕获输出内容。要实现需求,需用subprocess模块获取脚本输出,同时为避免阻塞GUI主线程,推荐结合子线程执行。
方法一:同步捕获输出(简单场景)
修改AI_click方法,使用subprocess.check_output捕获脚本标准输出:
import subprocess def AI_click(self): try: # 执行脚本并捕获输出,指定encoding将字节串转为字符串 output = subprocess.check_output( ["python", "detect_video.py", "--weights", "./checkpoints/custom-416", "--size", "416", "--model", "yolov4", "--video", "0", "--plate"], stderr=subprocess.STDOUT, # 同时捕获错误输出 encoding="utf-8" ) # 根据脚本输出格式提取目标字符串,这里假设输出是单行结果 target_str = output.strip() self.lineEdit.setText(target_str) except subprocess.CalledProcessError as e: # 脚本执行出错时显示错误信息 self.lineEdit.setText(f"执行失败: {e.output}")
方法二:子线程执行(推荐,避免GUI卡顿)
如果detect_video.py运行耗时较长,直接在主线程执行会导致界面冻结,需要用QThread异步执行:
- 定义子线程类:
from PyQt5.QtCore import QThread, pyqtSignal import subprocess class ScriptWorker(QThread): # 定义信号,传递输出结果和错误信息 output_ready = pyqtSignal(str) error_occurred = pyqtSignal(str) def run(self): try: result = subprocess.check_output( ["python", "detect_video.py", "--weights", "./checkpoints/custom-416", "--size", "416", "--model", "yolov4", "--video", "0", "--plate"], stderr=subprocess.STDOUT, encoding="utf-8" ) self.output_ready.emit(result.strip()) except subprocess.CalledProcessError as e: self.error_occurred.emit(f"执行错误: {e.output}")
- 修改
AI_click方法及添加槽函数:
def AI_click(self): # 创建线程实例 self.worker = ScriptWorker() # 连接信号到处理函数 self.worker.output_ready.connect(self.update_lineedit) self.worker.error_occurred.connect(self.show_error) # 启动线程 self.worker.start() def update_lineedit(self, text): # 更新lineEdit内容 self.lineEdit.setText(text) def show_error(self, error_msg): # 显示错误信息 self.lineEdit.setText(error_msg)
关键注意点
- 确保
detect_video.py确实将需要的字符串输出到标准输出(而非仅打印到控制台或写入文件)。 - 如果脚本输出多行内容,需要根据实际格式提取目标字符串(比如提取车牌号那一行)。
- 使用子线程时,注意避免重复创建线程,可在启动前判断线程状态。
内容的提问来源于stack exchange,提问作者Python_bot_here
相关产品推荐
相关产品推荐

