PyQt5 使用 QPlainTextEdit/QTextBrowser 与 Logging 结合后显示日志信息

PyQt5 使用 QPlainTextEdit/QTextBrowser 与 Logging 结合后显示日志信息

本文演示 PyQt5 如何与 Python 的标准库 Logging结合,然后输出日志信息到如:QPlainTextEdit QTextBrowser

代码结构

本文中全部代码全在test_QPlainTextEdit_Log.py这一个文件中编码,步骤中有变动的地方会注释标注,无改动的不会重复显示出来,需要看完整代码的,可直接移步到末尾。

一. 创建测试页面

创建一个最简单的窗口,其中的主要部件就是 QPlainTextEdit

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QPlainTextEdit_Log.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description :
"""
import sys
import logging
from typing import Callable

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPlainTextEdit, QTextBrowser
from PyQt5.QtCore import pyqtSignal, QObject


class LogWindow(QWidget):
    """显示日志的窗口"""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("日志输出")
        self.resize(600, 200)
        self.log = QPlainTextEdit(self)
        self.log.setReadOnly(True)  # 设置为只读模式
        layout = QVBoxLayout()
        layout.addWidget(self.log)
        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = LogWindow()
    window.show()
    sys.exit(app.exec_())

运行后,可以得到下面这样的窗口
image

二. 添加日志信号以及自定义处理器,并初始化日志

这一步,就需要结合PyQt5的信号机制与Logging标准库了,在初始化日式时,提供了三种处理器,其中最主要的就是 使用自定义的 QtHandler处理器,此处理器将把日志消息发送到对应的 Qt部件,如这里的 QPlainTextEdit

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QPlainTextEdit_Log.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description :
"""
class LogSignal(QObject):
    """日志信号"""
    log_signal = pyqtSignal(str)


class QtHandler(logging.Handler):
    """日志处理器"""

    def __init__(self, signal):
        super().__init__()
        self.signal = signal

    def emit(self, record):
        log_entry = self.format(record)
        self.signal.log_signal.emit(log_entry)


def init_log(update_log: Callable):
    """初始化日志系统"""
    log_signal = LogSignal()
    log_signal.log_signal.connect(update_log)  # 日志信号连接用于更新显示的槽函数

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    # 创建文件处理器,将日志写入文件(不需要可删除)
    file_handler = logging.FileHandler('application.log', encoding="utf-8")  # 文件处理器
    file_handler.setLevel(logging.DEBUG)  # 设置文件日志的级别
    file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
    logger.addHandler(file_handler)

    # 创建自定义处理器,就日志输出到 Qt 页面显示
    qt_handler = QtHandler(log_signal)  # 使用自定义的日志处理器
    qt_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
    logger.addHandler(qt_handler)

    # 控制台输出(不需要可删除,删除后控制台将不在输出日志信息,仅显示 print 打印)
    stream_handler = logging.StreamHandler()  # 输出到控制台
    stream_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s "))
    logger.addHandler(stream_handler)

    return logger

class LogWindow(QWidget):
    """显示日志的窗口"""
    ... # 忽略 无变化

三. 在显示窗口中调用日志,用于显示更新

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ File        : test_QPlainTextEdit_Log.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description :
"""
class LogWindow(QWidget):
    """显示日志的窗口"""

    def __init__(self):
        super().__init__()
        ... # 忽略

        self.logger = init_log(self.update_log)  # 初始化日志

        # 举例
        self.logger.info("这是一个消息")

    def update_log(self, log_text):
        self.log.append(log_text)  # 更新 QPlainTextEdit 内容

        # 将光标移动到文本的最后一行
        cursor = self.log.textCursor()
        cursor.movePosition(cursor.End)  # 移动光标到最后
        self.log.setTextCursor(cursor)

运行后的效果如下:
image

四. 在其他方法或类中输出消息

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : Qt5Examples
@ File        : test_QPlainTextEdit_Log.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description :
"""
def fun_logging(logger):
    """使用举例:在方法中输出日志"""
    logger.info("这是一个方法中的 INFO 消息")
    logger.warning("这是一个方法中的 WARNING 消息")
    logger.error("这是一个方法中的 ERROR 消息")


class ClassLogging(object):
    """使用举例:在类中输出日志"""

    def __init__(self, logger):
        self.logger = logger

    def log_output(self):
        self.logger.info("这是一个类中的 INFO 消息")
        self.logger.warning("这是一个类中的 WARNING 消息")
        self.logger.error("这是一个类中的 ERROR 消息")


class LogWindow(QWidget):
    """显示日志的窗口"""

    def __init__(self):
        super().__init__()
        ... # 忽略

        self.logger = init_log(self.update_log)  # 初始化日志

        # 举例
        self.logger.info("这是一个消息")

        # 举例:在其他模块中输出日志
        fun_logging(self.logger)
        log_example = ClassLogging(self.logger)
        log_example.log_output()

    def update_log(self, log_text):
        ... # 忽略 无变化

运行后的效果如下:
image

五. 使用 QTextBrowser 或者 QTextEdit

为啥要使用 QTextBrowser 或者 QTextEdit,如下:

  • QPlainTextEdit适合显示大量纯文本的显示,性能比QTextBrowser更强
  • QTextBrowser支持富文本(HTML、格式化文本等),可以显示带颜色、字体和其他格式的日志信息。但是文本是只读的。
  • QTextEdit 支持富文本(HTML、格式化文本等),可以显示带颜色、字体和其他格式的日志信息。文本是可以编辑的

举例,修改成 QTextBrowser显示,只需要修改两句话:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : Qt5Examples
@ File        : test_QPlainTextEdit_Log.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description :
"""
class LogWindow(QWidget):
    """显示日志的窗口"""

    def __init__(self):
        super().__init__()
        # self.log = QPlainTextEdit(self)
        self.log = QTextBrowser(self)  # 改成这句

    def update_log(self, log_text):
        # self.log.appendPlainText(log_text)  # 更新 QPlainTextEdit 内容
        self.log.append(log_text)  # 更新 QTextBrowser 内容

六. 完整代码

完整代码见:GitHubGitee

本文章的原文地址
GitHub主页

posted @   星尘的博客  阅读(237)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
点击右上角即可分享
微信分享提示