QT中QSignalMapper類的用法

QSignalMapper這個類並不是個新鮮概念, 早在Qt2裏就已經存在, 而且它的功能也是始終如一。 不過由於宣傳力度不夠(例子裏涉及到它的很少)瞭解這個類人可能還不是很多, 所以特此撰文介紹此類的功能和用法。

簡單的理解,可以把SignalMapper這個類看成是信號的翻譯和轉發器, 它可以把一個無參數的信號翻譯成帶int參數、QString參數、QObject*參數或者QWidget*參數的信號, 並將之轉發。 這麼一說大家有沒有聯想到該類的適用範圍呢? 呵呵, 是不是一下就想到了如果我有一堆的button, 可以把clicked事件放在一個函數裏處理, 只要給button編個號或者給button起個名就行了, 這樣就不用給每個button寫一個slot了,豈不是很方便?

 

下面這段代碼就實現了該功能:

//mainwin.h

class MainWin : public QWidget

{

Q_OBJECT

public:

    MainWin(QWidget *parent = 0);

private slots:

    void doClicked(const QString & btnname);//處理最終信號的槽

private: QSignalMapper *signalMapper;

};

 

//mainwin.cpp

MainWin::MainWin(QStringList texts, QWidget *parent) : QWidget(parent)

{

    QString buttontext = "btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn10";//10個button

    QStringList texts = buttontext.split(",");

    signalMapper = new QSignalMapper(this);

    QGridLayout *gridLayout = new QGridLayout;

    for (int i = 0; i < texts.size(); ++i)

    {

         QPushButton *button = new QPushButton(texts[i]);

         connect(button, SIGNAL(clicked()), signalMapper, SLOT(map ()));//原始信號傳遞給signalmapper

         signalMapper->setMapping (button, texts[i]);

        //設置signalmapper的轉發規則, 轉發爲參數爲QString類型的信號, 並把texts[i]的內容作爲實參傳遞。

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

    }

 

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

    setLayout(gridLayout);

}

 

void MainWin::doClicked(const QString& btnname)

{

    QMessageBox::information(this, "Clicked", btnname + " is clicked!");//顯示被按下的btn名稱。

}

 

從這個例子來看QSignalMapper的用法是非常簡單的, 也很容易理解。

*首先把原始不帶參數的信號連接到signalmapper的map槽函數, 這樣signalmapper能在第一時間接收到原始信號;

*其次調用setMapper方法告訴signalmapper怎樣去處理原始信號。 在這個例子中是把原始信號轉化爲一個帶QString參數的信號

*最後接收轉化後的帶參數信號, 這裏所把轉化後的信號與槽函數連接, 在槽函數中獲得需要的數據。

 

QSignalMapper類的功能核心是要建立一個從發出原始信號的object到需要的數據的映射(setMapper函數), 如果你的程序恰巧需要這樣的功能,那麼當然QSignalMapper就是當仁不讓的最佳選擇。 除了上述最常見的用法, 我們也來開動腦筋想想還有什麼別的場合適合使用這個類呢?

 

在Qt的examples裏僅有一個例子用到了QSignalMapper這個類, 在examples/mainwindow/mdi/mainwindow.cpp裏。 它的用法是將QWidget指針作爲參數, 然後菜單選中的信號映射到子Window的指針, 最終由QMainWindow來處理, 用於實現子窗口的切換。 這個用法很有些意思, 可以說是QSignalMapper的最佳用例, 建議大家學習一下。 這裏截取其中最核心的代碼, 有註釋應該很好看懂吧, 如果還是有問題就留言:

 

    //主類從QMainWindow派生

MainWindow::MainWindow()

{

    //...

    windowMapper = new QSignalMapper(this);

    connect(windowMapper, SIGNAL(mapped (QWidget *)), this, SLOT(setActiveSubWindow(QWidget *)));

    //轉發的信號直接連接到QMainWindow的setActiveSubWindow槽

    //...

}

 

void MainWindow::updateWindowMenu()

{

     //... QList windows = mdiArea->subWindowList();

    separatorAct->setVisible(!windows.isEmpty());

 

     for (int i = 0; i < windows.size(); ++i)

     {

          MdiChild *child = qobject_cast(windows.at(i)->widget());

          QString text;

          if (i < 9)

          {

               text = tr("&%1 %2").arg(i + 1) .arg(child->userFriendlyCurrentFile());

          }

          else

          {

               text = tr("%1 %2").arg(i + 1) .arg(child->userFriendlyCurrentFile());

          }

 

          QAction *action = windowMenu->addAction(text);

          action->setCheckable(true);

          action ->setChecked(child == activeMdiChild());

          connect(action, SIGNAL(triggered()), windowMapper, SLOT(map ()));//監控action的triggered信號                     windowMapper->setMapping (action, windows.at(i));//建立action指針到QWidget*的映射 }

          //...

}

原文:http://blog.csdn.net/cuteqt/article/details/4306900

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