Qt中添加自定義信號和槽帶來的一些問題


  • 背景:
    自己定義了一個類,並在類中添加了槽函數
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()函數連接信號和槽。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM