- 背景:
自己定義了一個類,並在類中添加了槽函數
class XImage : public QWidget
{
public:
XImage(QWidget *p = 0);
//重載繪制方法 update后會調用
void paintEvent(QPaintEvent* e);
public slots:
void openButton_clicked(); //添加的槽函數
protected:
QImage src;
};
然后建立信號和槽函數的連接
connect(ui->openButton,
SIGNAL(clicked()),
ui->image,
SLOT(openButton_clicked())
);
運行程序,Qt Creator提示
QObject::connect: No such slot QWidget::openButton_clicked() in ..\XImageEdit\widget.cpp:13
QObject::connect: (sender name: 'openButton')
QObject::connect: (receiver name: 'image')
也就是說,沒辦法調用到自己添加的槽函數。
- 解決
1 經過查找資料后發現,自己定義的類,如果想要實現信號和槽機制,需要在類中添加Q_OBJECT,添加后再此運行
class XImage : public QWidget
{
Q_OBJECT
public:
XImage(QWidget *p = 0);
//重載繪制方法 update后會調用
void paintEvent(QPaintEvent* e);
public slots:
void openButton_clicked(); //添加的槽函數
protected:
QImage src;
};
這時候,Qt Creator報錯
ximage.obj:-1: error: LNK2001: 無法解析的外部符號 "public: virtual struct QMetaObject const * __thiscall XImage::metaObject(void)const " (?metaObject@XImage@@UBEPBUQMetaObject@@XZ)
這是因為在類中添加了Q_OBJECT后,需要在執行一下qmake才可以。
- 以下參考自豆子老師的博客《Qt 學習之路 2(5):自定義信號槽》
只有繼承了QObject類的類,才具有信號槽的能力。所以,為了使用信號槽,必須繼承QObject。凡是QObject類(不管是直接子類還是間接子類),都應該在第一行代碼寫上Q_OBJECT。不管是不是使用信號槽,都應該添加這個宏。這個宏的展開將為我們的類提供信號槽機制、國際化機制以及 Qt 提供的不基於 C++ RTTI 的反射能力。因此,如果你覺得你的類不需要使用信號槽,就不添加這個宏,就是錯誤的。其它很多操作都會依賴於這個宏。注意,這個宏將由 moc(我們會在后面章節中介紹 moc。這里你可以將其理解為一種預處理器,是比 C++ 預處理器更早執行的預處理器。) 做特殊處理,不僅僅是宏展開這么簡單
下面總結一下自定義信號槽需要注意的事項:
- 發送者和接收者都需要是QObject的子類(當然,槽函數是全局函數、Lambda 表達式等無需接收者的時候除外);
- 使用 signals 標記信號函數,信號是一個函數聲明,返回 void,不需要實現函數代碼;
- 槽函數是普通的成員函數,作為成員函數,會受到 public、private、protected 的影響;
- 使用 emit 在恰當的位置發送信號;
- 使用QObject::connect()函數連接信號和槽。
- 參考的資料
1 https://www.devbean.net/2012/08/qt-study-road-2-custom-signal-slot/ 《Qt 學習之路 2(5):自定義信號槽》
2 https://bbs.csdn.net/topics/390732465 《求助 error LNK2001: 無法解析的外部符號 "public: virtual struct QMetaObject const * __thisc》
3 https://bbs.csdn.net/topics/390942343 《Qt Q_OBJECT問題出錯》