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());
}
相关推荐
用户805533698039 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner10 小时前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz5 天前
QML Hello World 入门示例
qt
xcyxiner8 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner9 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner9 天前
DicomViewer (添加模型类)3
qt
xcyxiner10 天前
DicomViewer (目录调整) 2
qt
xcyxiner10 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00612 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术12 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript