之前没有考虑写日志时采用单独的线程,而是将写日志的部分放在了主线程中实现,后面发现当程序输出的日志信息过多,程序长时间运行后会造成主线程的运行性能降低。故尝试创建一个单独的线程用来写日志。
此程序有一个弊端,运行时没有错误,但存在文件没有关闭,线程也不清楚结束了没,望大神加以指导修改将其完善。
程序的结构如下:
运行效果截图:
上图是第一个界面,密码和用户名为123,点击进入后弹出一个对话框,点击取消后原本填入的信息会被清除,密码验证不通过会弹出提示框。
此项目是基于应用程序的项目,以QDialog为基类,含有两个ui文件,分别为登录窗口和登录成功后显示的窗口,登录窗口中在两个输入的行编辑器中进行设置属性plcaeholderText,如下图:
输入的密码显示框还需再设置属性echoMode和placeholderText属性。
直接上代码:
main.cpp
#include "dialog.h"#include <QApplication>int main(int argc, char *argv[])
{if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QApplication a(argc, argv);Dialog w;w.show();return a.exec();
}
主程序中添加以下代码:
if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
是为了解决在ui界面设计的界面,通过预览查看其效果正常,但是运行程序时部分部件位置显示不正常的问题,在以前的博文中有所记录。
dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "welcomdlg.h"
#include "writelog.h"QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();void checkedLoginInInfo();void outPutLogMsg(QString strInfo,QString strIndex);protected:
// void closeEvent(QCloseEvent *event);
signals:void signalSendLogMsg(QString strMsg);private slots:void on_enterButton_clicked();void on_cancelButton_clicked();private:Ui::Dialog *ui;WelcomDlg *m_welcomDlg;WriteLog *m_writeLog;
};
#endif // 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_H
welcomdlg.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_H
writedlg.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。程序运行正常,但自我感觉日志文件被打开写日志接束后没有关闭,线程没有关闭,自己尝试过关闭线程与文件,但都无法很好的解决,望大神指导。