PyQt5中plainTextEdit触发AttributeError的问题及修复方案
问题描述
在PyQt5项目中,Parser类的setupUi方法创建了plainTextEdit控件,addPlainText方法用于向该控件追加文本。但在log.py中直接实例化Parser并调用addPlainText时,触发AttributeError,提示'Parser'对象不存在plainTextEdit属性。需要实现log.py的函数可跨文件向PlainEditText添加文本。
相关代码
ParserWindow.py
class Parser(object): def setupUi(self, ParserWindow): # 省略其他代码 self.plainTextEdit = QtWidgets.QPlainTextEdit(self.layoutWidget_6) self.plainTextEdit.setStyleSheet("font-family: 'Roboto Mono';\n" "font-weight: 600;\n" "font-size: 14px;\n" "line-height: 24px;\n" "\n" "letter-spacing: 0.75px;\n" "\n" "color: #B5B5BD;") self.plainTextEdit.setReadOnly(True) self.plainTextEdit.setObjectName("plainTextEdit") def addPlainText(self, text: str): self.plainTextEdit.appendPlainText(text) class ParserWindow(QtWidgets.QMainWindow, Parser): def __init__(self, *args, obj=None, **kwargs): super(ParserWindow, self).__init__(*args, **kwargs) self.setupUi(self)
log.py
from vendor.ParserWindow import Parser parser = Parser() def print_error(text: str): parser.addPlainText('[ERROR] {}'.format(text)) def print_info(text: str): parser.addPlainText('[INFO] {}'.format(text)) def print_warning(text: str): parser.addPlainText('[WARNING] {}'.format(text))
报错信息
File "C:\Users\fazuq\Desktop\project\twitter\vendor\ParserWindow.py", line 581, in addPlainText self.plainTextEdit.appendPlainText('{}'.format(text)) AttributeError: 'Parser' object has no attribute 'plainTextEdit'
问题原因
Parser类的plainTextEdit属性是在setupUi方法中初始化的,但你在log.py里直接实例化Parser后,从未调用过setupUi方法,导致plainTextEdit根本没被创建。而且Parser是Qt Designer生成的UI类,正确用法是让ParserWindow这种继承Qt窗口类的子类去调用setupUi,而非直接使用Parser实例。
解决方案
方法一:传递已初始化的ParserWindow实例给log模块
修改log.py,通过全局变量保存窗口实例,让日志函数调用该实例的方法:
# log.py from vendor.ParserWindow import ParserWindow # 保存全局窗口实例引用 parser_window = None def set_parser_window(window: ParserWindow): global parser_window parser_window = window def print_error(text: str): if parser_window: parser_window.addPlainText('[ERROR] {}'.format(text)) def print_info(text: str): if parser_window: parser_window.addPlainText('[INFO] {}'.format(text)) def print_warning(text: str): if parser_window: parser_window.addPlainText('[WARNING] {}'.format(text))
在主程序初始化窗口后,调用set_parser_window传递实例:
# 主程序入口文件 from vendor.ParserWindow import ParserWindow from vendor.log import set_parser_window if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) window = ParserWindow() set_parser_window(window) window.show() sys.exit(app.exec_())
方法二:使用Qt信号与槽机制(更符合Qt设计理念)
在ParserWindow中定义自定义信号,log.py发送信号,窗口接收后追加文本:
修改ParserWindow.py:
from PyQt5.QtCore import pyqtSignal class Parser(object): # 原代码不变 pass class ParserWindow(QtWidgets.QMainWindow, Parser): # 定义自定义日志信号 log_signal = pyqtSignal(str) def __init__(self, *args, obj=None, **kwargs): super(ParserWindow, self).__init__(*args, **kwargs) self.setupUi(self) # 连接信号到追加文本的方法 self.log_signal.connect(self.addPlainText)
修改log.py:
# log.py from PyQt5.QtWidgets import QApplication def print_error(text: str): # 遍历顶级窗口找到ParserWindow实例并发送信号 for widget in QApplication.instance().topLevelWidgets(): if hasattr(widget, 'log_signal'): widget.log_signal.emit('[ERROR] {}'.format(text)) break def print_info(text: str): for widget in QApplication.instance().topLevelWidgets(): if hasattr(widget, 'log_signal'): widget.log_signal.emit('[INFO] {}'.format(text)) break def print_warning(text: str): for widget in QApplication.instance().topLevelWidgets(): if hasattr(widget, 'log_signal'): widget.log_signal.emit('[WARNING] {}'.format(text)) break
方法三:直接查找已存在的窗口实例
如果程序中只有一个ParserWindow实例,可直接通过Qt应用实例查找:
# log.py from PyQt5.QtWidgets import QApplication from vendor.ParserWindow import ParserWindow def get_parser_window(): # 遍历顶级窗口找到ParserWindow实例 for widget in QApplication.instance().topLevelWidgets(): if isinstance(widget, ParserWindow): return widget return None def print_error(text: str): window = get_parser_window() if window: window.addPlainText('[ERROR] {}'.format(text)) def print_info(text: str): window = get_parser_window() if window: window.addPlainText('[INFO] {}'.format(text)) def print_warning(text: str): window = get_parser_window() if window: window.addPlainText('[WARNING] {}'.format(text))
内容的提问来源于stack exchange,提问作者Way Sanders
相关产品推荐
相关产品推荐

