Qt 在槽函式中獲取訊號傳送物件
Qt中提供了一個函式 qobject_cast(QObject *object),可以通過這個函式判斷訊號發出物件
Qt 幫助文件的解釋:
Returns the given object cast to type T if the object is of type T (or of a subclass); otherwise returns nullptr. If object is nullptr then it will also return nullptr.
The class T must inherit (directly or indirectly) QObject and be declared with the Q_OBJECT macro.
A class is considered to inherit itself.
The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.
- 簡單來說 就是使用這個函式會得到你轉型的的一個例項,但是這個類必須繼承自QObject 或者其子類並且宣告Q_OBJECT 這個巨集
- QT 幫助文件中一個Example
QObject *obj = new QTimer; QTimer *timer = qobject_cast<QTimer *>(obj);
這裡順便記錄一下RTTI 與RAII,RAII 通常應用於物件資源管理,RTTI 可以動態判斷物件型別,但使用RTTI會增加程式執行時間,這裡簡單記錄區分一下 。
- RTTI : Run-time type information
#include <iostream> #include <typeinfo> class Base { public: virtual ~Base() = default; }; class Derived : public Base {}; int main() { Base base; Derived derived; Base* ptr = &derived; Base& ref = derived; std::cout << typeid(base).name()<< std::endl; // class Base std::cout << typeid(derived).name()<< std::endl; // class Derived std::cout << typeid(ptr).name()<< std::endl; // class Base * std::cout << typeid(*ptr).name() << std::endl; //class Derived std::cout << typeid(ref).name() << std::endl; //class Derived }
- RAII : Resource Acquisition Is Initialization
程式碼來源 https://en.cppreference.com/w/cpp/language/raii std::mutex m; void bad() { m.lock(); // acquire the mutex f(); // if f() throws an exception, the mutex is never released if(!everything_ok()) return; // early return, the mutex is never released m.unlock(); // if bad() reaches this statement, the mutex is released } void good() { std::lock_guard<std::mutex> lk(m); // RAII class: mutex acquisition is initialization f(); // if f() throws an exception, the mutex is released if(!everything_ok()) return; // early return, the mutex is released }
下面是QT通過qobject_cast獲取訊號傳送物件的一個Demo,通過Qt Desinger 繪製兩個按鈕和一個文字框,將兩個按鈕的點選事件連線到同一個槽函式,在槽函式裡面判斷訊號的傳送者並作出不同的響應
主要的程式碼如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void onButtonClicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->leftButton,&QPushButton::clicked,this,&MainWindow::onButtonClicked);
connect(ui->rightButton,&QPushButton::clicked,this,&MainWindow::onButtonClicked);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onButtonClicked()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
ui->textLabel->setText(button->text());
if(ui->leftButton == button)
{
qDebug()<<"left Button clicked";
ui->textLabel->setStyleSheet("background-color:yellow");
button->setStyleSheet("background-color:yellow");
}
else
{
ui->textLabel->setStyleSheet("background-color:green");
button->setStyleSheet("background-color:green");
}
}
完整的程式碼已上傳Github