Qt线程写日志
之前沒有考慮寫日志時采用單獨的線程,而是將寫日志的部分放在了主線程中實現,后面發現當程序輸出的日志信息過多,程序長時間運行后會造成主線程的運行性能降低。故嘗試創建一個單獨的線程用來寫日志。
此程序有一個弊端,運行時沒有錯誤,但存在文件沒有關閉,線程也不清楚結束了沒,望大神加以指導修改將其完善。
程序的結構如下:
運行效果截圖:
上圖是第一個界面,密碼和用戶名為123,點擊進入后彈出一個對話框,點擊取消后原本填入的信息會被清除,密碼驗證不通過會彈出提示框。
此項目是基于應用程序的項目,以QDialog為基類,含有兩個ui文件,分別為登錄窗口和登錄成功后顯示的窗口,登錄窗口中在兩個輸入的行編輯器中進行設置屬性plcaeholderText,如下圖:
輸入的密碼顯示框還需再設置屬性echoMode和placeholderText屬性。
直接上代碼:
main.cpp
主程序中添加以下代碼:
if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);是為了解決在ui界面設計的界面,通過預覽查看其效果正常,但是運行程序時部分部件位置顯示不正常的問題,在以前的博文中有所記錄。
dialog.h
dialog.cpp
#include "dialog.h" #include "ui_dialog.h" #include <QDebug> #include <QMessageBox> #include <QDateTime>Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);m_welcomDlg = new WelcomDlg(this);m_writeLog = WriteLog::getInstance();connect(this,&Dialog::signalSendLogMsg,m_writeLog,&WriteLog::slot_receMsg); }Dialog::~Dialog() {delete ui; }void Dialog::checkedLoginInInfo() {QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg("開始驗證登錄信息!",str);QString strAccount = ui->lineEditAccount->text().trimmed();QString strPassword = ui->lineEditPassword->text();QString strMsg = "用戶名:" + strAccount + "密碼:" + strPassword;QString strInfo = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg(strMsg,strInfo);if(strAccount.compare("123") == 0 && strPassword.compare("123") == 0)//大小寫敏感的{QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg("登錄信息正確!",str);accept();//隱藏模式對話框m_welcomDlg->show();}else{QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg("登錄信息輸入錯誤!",str);QMessageBox::warning(this,tr("警告"),tr("用戶名或密碼錯誤,請重新輸入!"),QMessageBox::Yes);on_cancelButton_clicked();ui->lineEditAccount->setFocus();} }void Dialog::outPutLogMsg(QString strInfo,QString strIndex) {QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd: hh:mm:ss");strIndex.prepend(strTime);strIndex.append(strInfo);emit signalSendLogMsg(strIndex); }//void Dialog::closeEvent(QCloseEvent *event) //{ // QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__); // outPutLogMsg("執行關閉事件",str); // Q_UNUSED(event); // m_writeLog->closeFileThread(); //}void Dialog::on_enterButton_clicked() {checkedLoginInInfo(); }void Dialog::on_cancelButton_clicked() {ui->lineEditAccount->clear();//清空之后,恢復原來的提示文字ui->lineEditPassword->clear();QString strMsg = QString::number(0);strMsg = strMsg.prepend("數據被清空為:");QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg(strMsg,str); }welcomdlg.h
#ifndef WELCOMDLG_H #define WELCOMDLG_H#include <QDialog> #include "writelog.h"namespace Ui { class WelcomDlg; }class WelcomDlg : public QDialog {Q_OBJECTpublic:explicit WelcomDlg(QWidget *parent = nullptr);~WelcomDlg();void outPutLogMsg(QString strInfo,QString strIndex);signals:void signalSendLogMsg(QString strMsg); private:Ui::WelcomDlg *ui;WriteLog *m_writeLog; };#endif // WELCOMDLG_Hwelcomdlg.cpp
#include "welcomdlg.h" #include "ui_welcomdlg.h" #include <QDateTime>WelcomDlg::WelcomDlg(QWidget *parent) :QDialog(parent),ui(new Ui::WelcomDlg) {ui->setupUi(this);m_writeLog = WriteLog::getInstance();connect(this,&WelcomDlg::signalSendLogMsg,m_writeLog,&WriteLog::slot_receMsg);QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg("執行歡迎界面的構造函數!",str); }WelcomDlg::~WelcomDlg() {QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);outPutLogMsg("執行歡迎界面的析構函數!",str);delete ui; }void WelcomDlg::outPutLogMsg(QString strInfo,QString strIndex) {QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd: hh:mm:ss");strIndex.prepend(strTime);strIndex.append(strInfo);emit signalSendLogMsg(strIndex); }writedlg.h
#ifndef WRITELOG_H #define WRITELOG_H#include <QObject> #include <QMutex> #include <QThread> #include <QQueue> #include <QFile> #include <QTextStream>#define LOG_NAME "/log.txt"class WriteLog : public QObject {Q_OBJECT private:explicit WriteLog(QObject *parent = nullptr);void openLogFile();void writeLogInfo(); public:static WriteLog * getInstance();~WriteLog();// void closeFileThread(); signals:public slots:void slot_receMsg(QString str);void slot_threadStarted(); // void slot_threadFinished(); private:static QMutex m_mutex;static WriteLog *m_instance;QThread m_thread;QQueue<QString> m_queue;QFile *m_file; // QTextStream *m_textStream;//似乎不能chuang創建指針 };#endif // WRITELOG_Hwritedlg.cpp
#include "writelog.h" #include <QMutexLocker> #include <QCoreApplication> #include <QDateTime> #include <QDir>QMutex WriteLog::m_mutex; WriteLog *WriteLog::m_instance = nullptr; WriteLog::WriteLog(QObject *parent): QObject(parent) {//創建或打開日志文件openLogFile();this->moveToThread(&m_thread);connect(&m_thread,&QThread::started,this,&WriteLog::slot_threadStarted);connect(&m_thread,&QThread::finished,this,&QObject::deleteLater);m_thread.start(); }void WriteLog::openLogFile() {QString logDir = QCoreApplication::applicationDirPath() + "/log/" + QDateTime::currentDateTime().toString("yyyy-MM-dd");QDir dir(logDir);if(!dir.exists()){dir.mkpath(logDir);}logDir += LOG_NAME;m_file = new QFile(logDir);if(!m_file->open(QFile::WriteOnly | QFile::Text |QFile::Append));{return ;} // m_textStream = new QTextStream(m_file); }void WriteLog::writeLogInfo() {if(m_queue.isEmpty()){return ;}QString strMsg = m_queue.front();m_queue.pop_front();QTextStream textStream(m_file);textStream<<strMsg<<"\r\n";m_file->flush();//將緩存區數據刷新到文件中 }WriteLog *WriteLog::getInstance() {if(m_instance == nullptr){QMutexLocker locker(&m_mutex);m_instance = new WriteLog;}return m_instance; }WriteLog::~WriteLog()//沒有執行析構 {//關閉日志文件,退出線程 // QString preStr1("====================================End:"); // QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd"); // QString preStr2("===================================="); // if(m_file != nullptr) // { // m_file->close(); // delete m_file; // m_file = nullptr; // }// m_thread.quit(); // m_thread.wait(); }//void WriteLog::closeFileThread() //{ // QString preStr1("====================================End:"); // QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd"); // QString preStr2("===================================="); // preStr1 += time + preStr2 + "\r\n"; // m_queue.push_back(preStr1); // writeLogInfo(); if(m_file != nullptr) { m_file->close(); delete m_file; m_file = nullptr; } m_thread.requestInterruption(); m_thread.quit(); m_thread.wait(); //}void WriteLog::slot_receMsg(QString str) {m_queue.push_back(str);writeLogInfo(); }void WriteLog::slot_threadStarted() {QString preStr1("====================================Begin:");QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd");QString preStr2("====================================");preStr1 += time + preStr2 + "\r\n";QString str = QString("%1 :%2(%3): ").arg(__FILE__).arg(__FUNCTION__).arg(__LINE__);QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd: hh:mm:ss");QString info("寫日志線程啟動");strTime += str;info.prepend(strTime);info.prepend(preStr1);m_queue.push_back(info);writeLogInfo(); }//void WriteLog::slot_threadFinished() //{ qDebug()<<"線程完成!"; // m_queue.push_back("寫日志線程結束"); // writeLogInfo(); //}以上程序的編譯環境是在qt5.13.2,用的編譯器為MinGW32。程序運行正常,但自我感覺日志文件被打開寫日志接束后沒有關閉,線程沒有關閉,自己嘗試過關閉線程與文件,但都無法很好的解決,望大神指導。
總結
- 上一篇: ajax 在新选卡打开,开始使用 AJA
- 下一篇: 用python编excel统计表_Pyt