QT中想在QTextEdit控件中使用Qslog日志输出出现问题原因及解决方法

QT中自定义类时使用多重继承问题原因及解决方法

  1. 创建一个名为LogTextEditEx的类继承自QTextEdit和Destination,出现了多重继承的访问权限问题;原因:;class LogTextEditEx : public QTextEdit,Destination{}在Destination前少写了public;继承方式不正确,需要添加public继承,class LogTextEditEx : public QTextEdit,public Destination {};
  2. 在自定义类头文件中 添加Q_OBJECT // 确保有Q_OBJECT宏
  3. error: 'staticMetaObject' is not a member of
    'QsLogging::Destination'
    QMetaObject::SuperData::linkDestination::staticMetaObject(),
    原因:这个错误表明在moc生成的代码中,它试图访问QsLogging::Destination的staticMetaObject,但是Destination类没有这个成员。这是因为Destination可能不是QObject的子类,而我们的LogTextEditEx类试图同时继承QObject和Destination。
    在Qt中,如果一个类要使用信号槽(即包含Q_OBJECT宏),它必须直接或间接继承QObject。而QsLogging::Destination不是一个QObject派生类(它只是一个接口类)。因此,我们不能让一个类同时继承QObject和Destination,然后使用Q_OBJECT宏,因为moc会认为Destination也是一个QObject(但实际上不是)。
    解决方法:最简单的,将QTextEdit继承时放在最前面即可,其它复杂的没试过;
cpp 复制代码
#ifndef LOGTEXTEDITEX_H
#define LOGTEXTEDITEX_H
#include "QsLogDest.h"
#include <QTextEdit>
#include <QMutex>
#include <QObject>
using namespace QsLogging;
class LogTextEditEx : public QTextEdit,public Destination
{
        Q_OBJECT  // 确保有Q_OBJECT宏
public:
    explicit LogTextEditEx(QWidget* parent = nullptr);
    ~LogTextEditEx();
    void write(const QString &message, QsLogging::Level level) override;
    bool isValid() override;

private:
    struct LogMessage {
        QString message;
        int level;
    };
    QList<LogMessage> m_messageBuffer;
    QMutex m_bufferMutex;
    QTimer* m_updateTimer;

    void init();
    void updateTextEdit();
};

#endif // LOGTEXTEDITEX_H
cpp 复制代码
#include "logtexteditex.h"
#include <QScrollBar>
#include <QTimer>
#include <QMutexLocker>
LogTextEditEx::LogTextEditEx(QWidget *parent)
    : QTextEdit(parent)
{
    init();
}
LogTextEditEx::~LogTextEditEx()
{

}
void LogTextEditEx::init()
{
    // 设置为只读
    setReadOnly(true);

    // 设置字体
    QFont font("Consolas", 9);
    setFont(font);

    // 创建定时器,批量更新UI以提高性能
    m_updateTimer = new QTimer(this);
    m_updateTimer->setInterval(100); // 100ms更新一次
    connect(m_updateTimer, &QTimer::timeout,
            this, &LogTextEditEx::updateTextEdit);
    m_updateTimer->start();
}

void LogTextEditEx::write(const QString &message, QsLogging::Level level)
{
    QMutexLocker locker(&m_bufferMutex);
    m_messageBuffer.append({message, static_cast<int>(level)});
}

bool LogTextEditEx::isValid()
{
    return true;
}

void LogTextEditEx::updateTextEdit()
{
    QMutexLocker locker(&m_bufferMutex);
    if (m_messageBuffer.isEmpty())
        return;

    // 批量处理日志消息
    QList<LogMessage> messages = m_messageBuffer;
    m_messageBuffer.clear();
    locker.unlock();

    // 准备HTML内容
    QString html;
    for (const auto& msg : messages) {
        QString color;
        switch (msg.level) {
        case 0: color = "gray"; break;      // Trace
        case 1: color = "blue"; break;      // Debug
        case 2: color = "green"; break;     // Info
        case 3: color = "orange"; break;    // Warn
        case 4: color = "red"; break;       // Error
        case 5: color = "darkred"; break;   // Fatal
        default: color = "black";
        }

        html += QString("<span style='color:%1'>%2</span><br>")
                .arg(color)
                .arg(msg.message.toHtmlEscaped());
    }

    // 更新文本编辑框
    QTextCursor cursor(document());
    cursor.movePosition(QTextCursor::End);
    cursor.insertHtml(html);

    // 限制最大行数
    const int maxLines = 1000;
    int lineCount = document()->lineCount();
    if (lineCount > maxLines) {
        cursor.movePosition(QTextCursor::Start);
        cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor,
                            lineCount - maxLines);
        cursor.removeSelectedText();
    }

    // 自动滚动
    verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
相关推荐
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
伞伞悦读4 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车4 天前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁4 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
孙启超4 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int4 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++
慧都小项4 天前
当边缘AI上产线:QtitanDocking 如何让工业 HMI 实现多视图协同
人工智能·qt·ui·边缘计算·qt6.3
CoderYanger4 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读4 天前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json
CCCCCCCCharlie4 天前
Linux进程控制四大核心操作
linux·开发语言