今天在使用QT官方提供的函数qInstallMessageHandler输出日志时,因为这个函数的参数需要传的是一个函数,当这个函数是成员函数的时候需要是一个静态函数。但同时当我又需要在这个静态函数中发送消息,这时候就出现问题了,在静态函数中发送信号,会报错:非静态成员函数的非法调用。
但同时我们的信号又不能被声明为静态的,这时候我们就需要在静态函数中发送信号,我这里使用的方法就是新建一个类,用静态函数发送信号,用新建的类接收,然后再将这个信号发送出去。
虽然信号不能被声明为静态的,但是类的对象可以是静态的,那我们就可以在静态函数中发射一个静态对象的信号。
代码示例
Tool类中静态函数发送信号,由MainWindow接收
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
// 工具类,用于转发静态信号
class Tool : public QObject
{
Q_OBJECT
public:
explicit Tool(QObject *parent = nullptr);
static void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
private:
static Tool *mytool; // 定义一个静态ToolA类
signals:
void SigDeliverMess(QString message); // 真正发出去的信号
void SigDeliverMessStatic(QString message); // 内部信号 用于静态函数调用
private slots:
void SlotDeliverMessStatic(QString message); // 内部槽 用于响应内部信号
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void ShowDebugContent(const QString &text);
private:
Ui::MainWindow *ui;
Tool *m_tool;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDateTime>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_tool = new Tool();
connect(m_tool,&Tool::SigDeliverMess, this, &MainWindow::ShowDebugContent);
qInstallMessageHandler(m_tool->myMessageOutput);
}
MainWindow::~MainWindow()
{
delete ui;
delete m_tool;
}
void MainWindow::on_pushButton_clicked()
{
qDebug() << "hahaha";
}
void MainWindow::ShowDebugContent(const QString &text)
{
ui->textEdit->append(text);
}
Tool *Tool::mytool = nullptr; // 类外初始化静态Tool类 mytool
Tool::Tool(QObject *parent) : QObject(parent)
{
mytool = this;
connect(this,&Tool::SigDeliverMessStatic,this,&Tool::SlotDeliverMessStatic); // 关联内部信号与槽
}
void Tool::SlotDeliverMessStatic(QString message)
{
emit mytool->SigDeliverMess(message); // 发射出去信号
}
void Tool::myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
QString message = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + "\r\n";
message.append(localMsg);
emit mytool->SigDeliverMessStatic(message);
}