PyQt5跨文件/类向textEdit发送消息时避免弹出调试窗口的问题
问题原因
你现在的代码有两个核心错误:
- 每次触发写日志逻辑时都重新创建
Debugger_MainWindow实例,还把主程序的MainWindow对象传入Debugger_setupUi方法,会直接覆盖主界面的UI布局 - 没有分离「调试窗口实例」和「窗口显示逻辑」,默认只要初始化UI就会触发窗口绘制,没有做隐藏控制
实现方案
核心思路是:程序启动时就初始化一次调试窗口,默认设置为隐藏状态,所有调试日志直接写入窗口内的textEdit控件,只有用户主动触发打开操作时才调用show()方法显示窗口,写日志操作完全不关联窗口显示逻辑。
第一步:修改debugger.py
把原来的纯UI setup类改成继承QMainWindow的独立窗口类,内置日志写入方法,初始化完成后默认不显示窗口:
import os, time from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtGui import QTextCursor class DebuggerWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupUi() # 初始化后默认隐藏窗口,不主动弹出 self.hide() def append_log(self, text): """专门给外部调用的日志写入方法""" self.txtEdit_debugger.insertPlainText(f"{text}\n") # 自动滚动到底部 self.txtEdit_debugger.moveCursor(QTextCursor.End) def setupUi(self): self.setObjectName("DebuggerWindow") self.resize(800, 600) self.centralwidget = QtWidgets.QWidget(self) self.centralwidget.setObjectName("centralwidget") self.lbl_info = QtWidgets.QLabel(self.centralwidget) self.lbl_info.setGeometry(QtCore.QRect(90, 450, 451, 61)) self.lbl_info.setObjectName("lbl_info") self.lbl_tittle = QtWidgets.QLabel(self.centralwidget) self.lbl_tittle.setGeometry(QtCore.QRect(280, 40, 56, 15)) self.lbl_tittle.setObjectName("lbl_tittle") self.txtEdit_debugger = QtWidgets.QTextEdit(self.centralwidget) self.txtEdit_debugger.setGeometry(QtCore.QRect(70, 80, 481, 361)) self.txtEdit_debugger.setObjectName("txtEdit_debugger") self.txtEdit_debugger.setReadOnly(True) self.chkb_on_off_debugger = QtWidgets.QCheckBox(self.centralwidget) self.chkb_on_off_debugger.setGeometry(QtCore.QRect(90, 500, 30, 20)) self.chkb_on_off_debugger.setObjectName("chkb_on_off_debugger") self.chkb_on_off_debugger.setCheckable(True) self.lbl_on_off_debugger = QtWidgets.QLabel(self.centralwidget) self.lbl_on_off_debugger.setGeometry(QtCore.QRect(110, 500, 120, 20)) self.lbl_on_off_debugger.setObjectName("lbl_on_off_debugger") self.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.retranslateUi() QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): _translate = QtCore.QCoreApplication.translate self.setWindowTitle(_translate("DebuggerWindow", "调试窗口")) self.lbl_info.setText(_translate("DebuggerWindow", "当前为只读模式,所有日志实时同步")) self.lbl_tittle.setText(_translate("DebuggerWindow", "调试日志")) self.lbl_on_off_debugger.setText(_translate("DebuggerWindow", "实时接收日志")) self.lbl_on_off_debugger.adjustSize() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) ui = DebuggerWindow() ui.show() sys.exit(app.exec_())
第二步:修改main.py
主程序启动时只初始化一次调试窗口,写日志时直接调用append_log方法即可,不会弹出窗口;如果需要打开调试窗口,单独加个按钮或者菜单项调用debug_window.show()就行:
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import * from PyQt5.QtCore import pyqtSlot, QThreadPool, QTimer from PyQt5.QtGui import QColor, QKeySequence, QIcon, QTextCursor # 导入修改后的调试窗口类 from Debugger import DebuggerWindow class Ui_MainWindow(object): def __init__(self): super().__init__() # 初始化时就创建调试窗口实例,全程只创建一次 self.debug_win = DebuggerWindow() ###### Methods def print_text(self): # 直接调用日志写入方法,不会触发窗口显示 self.debug_win.append_log("hi,这是一条测试日志") # 如果需要点击按钮时才打开调试窗口,放开下面这行注释即可 # self.debug_win.show() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(500, 500) # 如果你没有styles.qss文件就把下面这行注释掉,不然会报错 # MainWindow.setStyleSheet(open("styles.qss", "r").read()) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") ##Group box self.gpb_spell_main = QtWidgets.QGroupBox(self.centralwidget) self.gpb_spell_main.setGeometry(QtCore.QRect(10, 5, 290, 230)) self.gpb_spell_main.setObjectName("gpb_spell_main") self.gpb_spell_main.setCheckable(True) self.gpb_spell_main.setChecked(False) ##Button spell_main_color = QColor(255, 0, 255) self.btn_spell_main = QtWidgets.QPushButton(self.gpb_spell_main) self.btn_spell_main.setGeometry(QtCore.QRect(10, 35, 120, 27)) self.btn_spell_main.setObjectName("btn_spell_main") self.btn_spell_main.clicked.connect(self.print_text) # 加个单独的按钮用来打开调试窗口 self.btn_open_debug = QtWidgets.QPushButton(self.gpb_spell_main) self.btn_open_debug.setGeometry(QtCore.QRect(10, 80, 120, 27)) self.btn_open_debug.setText("打开调试窗口") self.btn_open_debug.clicked.connect(self.debug_win.show) MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "主程序")) self.gpb_spell_main.setTitle(_translate("HeallingWindow", "功能区")) self.btn_spell_main.setText(_translate("MainWindow", "写入测试日志")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
效果说明
- 点击「写入测试日志」按钮时,日志会直接写入调试窗口的textEdit控件,不会弹出调试窗口
- 点击「打开调试窗口」按钮时才会显示调试界面,之前写入的所有日志都已经存在在控件里
- 调试窗口打开状态下,新写入的日志会实时同步显示,不需要刷新
内容的提问来源于stack exchange,提问作者devxen21
相关产品推荐
相关产品推荐

