QSignalMapper的使用和使用場景 QSignalMapper的使用和使用場景

QSignalMapper的使用和使用場景

 

 

QSignalMapper的使用和使用場景

QSignalMapper類收集了一系列的無參信號,然後使用相對於信號發送者來說的整數、字符串或控件參數來重新發送它們。(一開始沒讀懂沒關係,看完就懂了)

常見場景

其實,該類的一個典型的使用場合是,大量控件都要相應槽函數,而這些槽函數的實現又大致相同。這種情況下,最直接的辦法就是仍然爲每一個控件的相應信號創建一個槽函數。但這會導致代碼的大量重複。此時,我們就可以使用QSignalMapper來實現這種需求。

  1. QSignalMapper類支持使用setMapping()函數將一個特定的整數或字符串和一個特定的對象關聯起來。

void QSignalMapper::setMapping

  1. 可以將對象的信號(比如button的clicked)連接到QSignalMapper對象的map()槽函數上,而map()槽函數又會使用與對象相關聯的整數或字符串來發送mapped()信號。

  2. 所以,我們只要將我們定義的一個槽函數連接到mapped()信號,即可處理大量相似控件的槽函數。

我們以一個例子來說明。其界面如下:(例子來自csdn第二篇文章,稍微的補充修改)

請仔細看補充的註釋。將會對應上面寫的三條。
初始化界面的代碼如下:

void Widget::InitUi()
{
    names << "宋江" << "盧俊義" << "吳用" << "公孫勝"
          << "關勝" << "林沖" << "秦明" << "呼延灼"
          << "花榮" << "柴進" << "李應" << "朱仝"
          << "魯智深" << "武松" << "董平" << "張清";
    QGridLayout *gridLayout = new QGridLayout;
    for (int i = 0; i < names.size(); ++i)
    {
        QPushButton *button = new QPushButton(names[i]);
        // 使用setMapping()函數將一個特定的整數或字符串或對象(qt doc截圖那些)和一個特定的對象關聯起來。
        signalMapper->setMapping(button, names[i]);
        // 這就是可以將對象的信號連接到QSignalMapper對象的map()槽函數上
        connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
        gridLayout->addWidget(button, i / 4, i % 4);
    }
    // 將我們定義的槽函數連接到mapped()信號 // 注意看mapped的寫法
    connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(ShowName(QString)));
    setLayout(gridLayout);
}

其中,names是一個私有的QStringList變量,存儲每一個按鈕上的文本內容。ShowName()是我們定義的一個槽函數,我們就是讓所有按鈕的clicked()信號都連接到這個槽函數。在窗口類中聲明如下:

public slots:
    void ShowName(QString name);
 
private:
    void InitUi();
 
private:
    Ui::Widget *ui;
    QSignalMapper* signalMapper;
    QStringList names;

ShowName()槽函數的實現如下,簡單的彈出一個消息框,顯示當前點擊的按鈕的文本內容:

void Widget::ShowName(QString name)
{
    QMessageBox::information(this, "Name", name);
}

當然,別忘了在構造函數中,調用我們的初始化界面的方法,以及實例化我們的signalMapper對象。如下:

ui->setupUi(this);
    signalMapper = new QSignalMapper(this);
    InitUi();

下面是參考。可看可不看

這篇寫的不錯,搬運爲Markdown了 可以看一下

QSignalMapper類可以看成是信號的翻譯和轉發器。
它可以把一個無參的信號翻譯成帶int參數、QString參數、 QObject* 參數或者QWidget *參數的信號,並將之轉發。
QSignalMapper類的功能核心是要建立一個從原始信號的object到需要的數據的映射(setMapper函數)。 map()作爲QSignalMapper的一個槽函數,將根據setMapping規則轉發mapped()信號。
QSignalMapper可將多個有類似處理方式signal用一個slot實現,相當於將N個一對一映射通過集中轉換成多對一映射。

例子:有一堆button,可以把clicked()事件放在一個函數裏進行處理,只要給button編個號或者給button起個名字就行,這樣就不用給每個button寫一個slot函數了,方便很多。

//mywidget.h
class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = 0);

signals:

public slots:
    //處理最終信號的槽
    void doClicked(const QString &btnName);

private:
    QSignalMapper *signalMapper;

};
//mywidget.cpp
MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent)
{
    QString buttonText = "btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10";
    QStringList textList = buttonText.split(",");
    signalMapper = new QSignalMapper(this);
    QGridLayout *gridLayout = new QGridLayout;

    for(int i=0; i<textList.size(); ++i)
    {
        //動態創建按鈕
        QPushButton *button = new QPushButton(textList[i]);

        //原始信號傳遞給signalMapper
        connect(button,SIGNAL(clicked()),signalMapper,SLOT(map()));
        //設置signalMapper的轉發規則,轉發爲參數爲QString類型的信號,並把textList[i]的內容作爲實參傳遞
        signalMapper->setMapping(button, textList[i]);

        gridLayout->addWidget(button, i/3, i%3);
    }

    //將轉發的信號連接到最終的槽函數上
    connect(signalMapper,SIGNAL(mapped(QString)),this,SLOT(doClicked(QString)));

    setLayout(gridLayout);
}

void MyWidget::doClicked(const QString &btnName)
{
    //顯示被按下的button名稱
    QMessageBox::information(this,"Clicked",btnName+" is clicked !");
}

例子說明:
首先把原始不帶參數的信號連接到signalMapper的map()槽函數,這樣signalMapper能在第一時間接收到原始信號;
其次調用setMapper方法建立映射關係,告訴signalMapper怎樣處理原始信號。這個例子是把原始信號轉化爲一個帶QString參數的信號;
最後接收轉化後的帶參數信號,這裏把轉化後的信號與槽函數連接,在槽函數中獲得需要數據

映射關係可以通過removeMappings()移除;
setMapping函數的參數只有四種,並且要嚴格按照格式寫入,第一種const QString&,第二種int,第三種QObject*,第四種QWidget *,對於後兩種,需要的是他們的子類,則在信號處理的函數裏進行類型轉化.

參考

https://doc.qt.io/qt-5/qsignalmapper.html#details

https://blog.csdn.net/Amnes1a/article/details/70050788

https://blog.csdn.net/u011125673/article/details/51218196

https://blog.csdn.net/Amnes1a/article/details/70050788

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章