Qt自定义控件之日志控件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt自定义控件之日志控件相关的知识,希望对你有一定的参考价值。
摘要
一般的应用程序都需要在界面上显示日志信息, glog是google的轻量级日志库,本文结合glog,实现了一个简单的线程安全的日志控件。
正文
关于glog的使用,网上有好多介绍的资料,本文参考里面列出了一些,这里就不介绍了。下面列出日志控件的实现要点:
1、日志控件继承自google::LogSink,重新实现其virtual send()函数,自定义日志处理逻辑。
2、调用google::AddLogSink(this),将日志控件添加到glog的转发容器中;
3、日志控件使用QplainTextEdit来显示日志信息;
4、日志控件维护一个线程安全的日志的vector,使用定时器定时从vector中取出日志,并在QplainTextEdit中显示;
本文代码在vs2015和qt5.7.1的64位编译下进行测试。
下载地址:https://github.com/binbinneu/qt_practice
实现代码如下:
class LogWidget : public QWidget, public google::LogSink { Q_OBJECT; public: LogWidget(QWidget *parent = 0); virtual ~LogWidget(); public: virtual void send(google::LogSeverity severity, const char* full_filename, const char* base_filename, int line, const struct ::tm* tm_time, const char* message, size_t message_len); public Q_SLOTS: void refresh(); private: QPlainTextEdit *log_widget_; QTimer timer_; std::mutex mutex_; typedef std::pair<std::string, google::LogSeverity> MessageType; std::vector<MessageType> message_vec_; const int MAXIMUM_BLOCK_COUNT; const int REFESH_TIME; };
LogWidget::LogWidget(QWidget *parent /*= 0*/) : QWidget(parent), MAXIMUM_BLOCK_COUNT(10000), REFESH_TIME(100) { QHBoxLayout *layout = new QHBoxLayout(); layout->setMargin(0); setLayout(layout); //采用QPlainTextEdit显示日志信息 log_widget_ = new QPlainTextEdit(this); log_widget_->setMaximumBlockCount(MAXIMUM_BLOCK_COUNT); log_widget_->setReadOnly(true); layout->addWidget(log_widget_); //定时器,定时刷新日志 QObject::connect(&timer_, SIGNAL(timeout()), this, SLOT(refresh())); timer_.start(REFESH_TIME); //添加到glog的转发容器中 google::AddLogSink(this); } LogWidget::~LogWidget() { timer_.stop(); QObject::disconnect(&timer_, SIGNAL(timeout()), this, SLOT(refresh())); google::RemoveLogSink(this); } void LogWidget::refresh() { std::lock_guard<std::mutex> lock(mutex_); if (!message_vec_.empty()) { for (const auto &message : message_vec_) { log_widget_->appendPlainText(QString::fromLocal8Bit(message.first.c_str())); } } message_vec_.clear(); } void LogWidget::send(google::LogSeverity severity, const char* full_filename, const char* base_filename, int line, const struct ::tm* tm_time, const char* message, size_t message_len) { std::ostringstream message_stream; message_stream.fill(‘0‘); message_stream << "[" << google::LogSeverityNames[severity][0] << std::setw(2) << 1 + tm_time->tm_mon << std::setw(2) << tm_time->tm_mday << ‘ ‘ << std::setw(2) << tm_time->tm_hour << ‘:‘ << std::setw(2) << tm_time->tm_min << ‘:‘ << std::setw(2) << tm_time->tm_sec << ‘ ‘ << full_filename << ‘:‘ << line << "] "; message_stream << std::string(message, message_len); std::string message_str = message_stream.str(); std::lock_guard<std::mutex> lock(mutex_); message_vec_.push_back(MessageType(message_str, severity)); }
测试代码:
void thread_fun() { for (int i=0; i<1000000; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); LOG(INFO) << "INFO"; LOG(WARNING) << "WARNING"; LOG(ERROR) << "ERROR"; } } int main(int argc, char *argv[]) { QApplication a(argc, argv); LogWidget w; w.show(); QString log_path = QCoreApplication::applicationDirPath() + "/"; google::InitGoogleLogging(argv[0]); google::SetLogDestination(google::INFO, log_path.toStdString().c_str()); google::SetLogDestination(google::WARNING, log_path.toStdString().c_str()); google::SetLogDestination(google::ERROR, log_path.toStdString().c_str()); google::SetLogDestination(google::FATAL, log_path.toStdString().c_str()); for (int i=0; i<10; ++i) { std::thread t(thread_fun); t.detach(); } int b = a.exec(); google::ShutdownGoogleLogging(); return b; }
输出结果:
参考
1、http://blog.csdn.net/breaksoftware/article/details/51363353
2、http://www.cnblogs.com/davidyang2415/p/3861109.html
以上是关于Qt自定义控件之日志控件的主要内容,如果未能解决你的问题,请参考以下文章