背景
由于我们的程序在使用时,在进行串口通信或者网络通信时,想实时的看到关键日志信息或者错误信息,所以需要在软件中集成一个日志控制台的功能。
参考 visual studio和 qtcreator等各种IDE,在IDE的下面都会有一个日志输出窗口,而本次我们也使用QPlainTextEdit 来实现一个简单的日志输出窗口。
程序
#pragma once
#include <QWidget>
#include <QPlainTextEdit>
class QPlainTextEdit;
class LogWidget : public QWidget
{
Q_OBJECT
public:
explicit LogWidget(QWidget* parent = nullptr);
~LogWidget();
public:
void setMaxRow(uint32_t newMaxRow);
uint32_t getMaxRow()const;
void clear();
void append(const QString& text, const QString& type = QString("Info"),
const QColor& color = QColor(100, 184, 255));
private:
uint32_t m_totalRow = 0;
uint32_t m_maxRow = 1000;
QPlainTextEdit* m_edit = nullptr;
QTextCharFormat fmt;
};
#include <QVBoxLayout>
#include <QDateTime>
#include "logwidget.h"
LogWidget::LogWidget(QWidget* parent):
QWidget(parent)
{
auto box = new QVBoxLayout(this);
box->setSpacing(0);
box->setMargin(3);
m_edit = new QPlainTextEdit(this);
m_edit->setReadOnly(false);
m_edit->setUndoRedoEnabled(false);
box->addWidget(m_edit);
setContentsMargins(2, 10, 2, 10);
}
LogWidget::~LogWidget()
{
}
void LogWidget::setMaxRow(uint32_t newMaxRow)
{
m_maxRow = newMaxRow;
}
uint32_t LogWidget::getMaxRow() const
{
return m_maxRow;
}
void LogWidget::clear()
{
m_totalRow = 0;
m_edit->clear();
}
void LogWidget::append(const QString& text, const QString& type, const QColor& color)
{
auto time = QTime::currentTime().toString("HH:mm:ss zzz");
fmt.setForeground(QBrush(color));
m_edit->mergeCurrentCharFormat(fmt);
QString content = QString("[%1][%2]%3").arg(time, type, text);
m_edit->appendPlainText(content);
m_edit->moveCursor(QTextCursor::End);//移动光标到最后一行
m_totalRow ++;
if (m_totalRow >= m_maxRow) {
auto cursor = m_edit->textCursor();
cursor.setPosition(0);
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
}
}
说明
此widget支持设置最大显示行数。并支持根据不同的日志等级显示不同的颜色,支持显示日志的执行时间。
此widget可以当作一个基础的UI组件,可被QT程序加载到任何想显示的布局里面,比如添加到dockwidget中可被拖动。
关于为什么选择 QPlainTextEdit 而不是 QTextEdit,有以下2个原因:
1、我们的日志是纯文本内容,所以QPlainTextEdit就够了。
2、在段落布局上,QPlainTextEdit 的性能是高于QTextEdit的,我这边是测试验证过的,在大量数据的时候,QPlainTextEdit 在dockwidget中进行拖动就不会卡顿,而QTextEdit卡顿非常严重。
其他
当然,如果想要增加查找功能也比较简单,创建一个dialog,包含一个 lineedit,或者使用 QInputDialog 更方便,然后在dialog的按钮事件中执行下面的代码:
void LogWidget::find()
{
bool ok;
QString text = QInputDialog::getText(this, 查找"),
tr("内容:"), QLineEdit::Normal,
QDir::home().dirName(), &ok);
if (ok && !text.isEmpty())
{
show_findText(text);
}
}
void LogWidget::show_findText(const QString& findtext)
{
if(m_edit->find(findtext,QTextDocument::FindBackward))//查找后一个
{
// 查找到后高亮显示
QPalette palette = m_edit->palette();
palette.setColor(QPalette::Highlight,palette.color(QPalette::Active,QPalette::Highlight));
m_edit->setPalette(palette);
}
else
{
QMessageBox::information(this,("注意"),("没有找到内容"),QMessageBox::Ok);
}
}
关注公众号 QTShared,带你探索更多 C++/QT 相关知识。