C++ 入門指南 - SIGNAL 與 SLOT

SIGNAL 為使用者的動作, SLOT 則是程式設定對使用者動作的反應




例如我們希望使用者輸入文字後,按下 Enter 就會記錄使用者所輸入的文字,這時,我們需要一個新的 inputText 變數成員 (variable member) 與 inputContact() 函數成員 (function member) 來完成這樣工作
#ifndef GUIDEMO_H
#define GUIDEMO_H

#include <QWidget>

class QLabel;
class QLineEdit;
class QPushButton;

class GUIDemo : public QWidget {
    Q_OBJECT

public:
    GUIDemo(QWidget *parent = 0);

public slots:
    void inputContact();

private:
    QLabel *display;
    QLineEdit *inputField;
    QLineEdit *outputField;
    QPushButton *newButton;
    QPushButton *loadButton;
    QPushButton *saveButton;
    QPushButton *encodeButton;
    QPushButton *decodeButton;
    QPushButton *clearButton;
    QPushButton *copyButton;
    
    QString inputText;
};

#endif

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:GUIDemo.h
    功能:示範 C++ 程式 
    作者:張凱慶
    時間:西元 2012 年 10 月 */


inputContact() 的工作很簡單,由 inputField 呼叫 text() 取得使用者輸入的文字,然後將該文字儲存到 inputText 中,最後 display 呼叫 setText() 設定提示訊息
void GUIDemo::inputContact() {
    inputText = inputField->text();
    display->setText("Your input is '" + inputText + "'.");
}


GUIDemo 的建構子 (constructor) 需要加入 connect() 函數 (function) ,用以連結 SIGNALSLOT
connect(inputField, SIGNAL(returnPressed()), this, SLOT(inputContact()));


connect() 需要四個參數 (parameter) ,前兩個參數跟 SIGNAL 有關,第一個參數為使用者操作的視窗元件,此例為 inputField ,第二個參數則是使用者對該視窗元件的動作,按下 Enter 就是 returnPressed() ,然後當作巨集 SIGNAL() 的參數。


connect() 的後兩個參數跟 SLOT 有關,第三個參數為發生反應的物件,此例為 GUIDemo 本身,因此用 this 當參數, this 也是關鍵字 (keyword) 之一,表示類別中的自己。最後一個參數則是 GUIDemo 的反應,我們將其定義在 inputContact() ,同樣的, SLOT() 也是巨集。


完整的實作檔 GUIDemo.cpp 如下
#include <QtGui>
#include "GUIDemo.h"

GUIDemo::GUIDemo(QWidget *parent) : QWidget(parent) {
    QLabel *input = new QLabel(tr("Input:"));
    QLabel *output = new QLabel(tr("Output:"));
    display = new QLabel(tr("something happened"));
    
    inputField = new QLineEdit;
    connect(inputField, SIGNAL(returnPressed()), this, SLOT(inputContact()));
    outputField = new QLineEdit;
    outputField->setReadOnly(true);
    
    newButton = new QPushButton(tr("New"));
    loadButton = new QPushButton(tr("Load"));
    saveButton = new QPushButton(tr("Save"));
    encodeButton = new QPushButton(tr("Encode"));
    decodeButton = new QPushButton(tr("Decode"));
    clearButton = new QPushButton(tr("Clear"));
    copyButton = new QPushButton(tr("Copy"));
    
    QGridLayout *layout = new QGridLayout;
    
    layout->addWidget(input, 0, 0);
    layout->addWidget(inputField, 0, 1, 1, 6, 0);
    
    layout->addWidget(output, 1, 0);
    layout->addWidget(outputField, 1, 1, 1, 6, 0);
    
    layout->addWidget(newButton, 2, 0);
    layout->addWidget(loadButton, 2, 1);
    layout->addWidget(saveButton, 2, 2);
    layout->addWidget(encodeButton, 2, 3);
    layout->addWidget(decodeButton, 2, 4);
    layout->addWidget(clearButton, 2, 5);
    layout->addWidget(copyButton, 2, 6);
    
    layout->addWidget(display, 3, 0, 1, 7, 0);
    
    setLayout(layout);
    setWindowTitle(tr("GUIDemo"));
}

void GUIDemo::inputContact() {
    inputText = inputField->text();
    display->setText("Your input is '" + inputText + "'.");
} 

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:GUIDemo.cpp
    功能:示範 C++ 程式 
    作者:張凱慶
    時間:西元 2012 年 10 月 */


倒是 main.cpp 不需要修改。編譯執行,輸入 "There is no spoon." 後結果如下



我們要來替每個按鈕設計 SLOT ,然後用 connect() 連結 SIGNAL ,不過,有沒有發現 inputText 是 QString 型態 (type) 的,這是因為從 QLineEdit 取得的文字預設就是 QString 型態,可是 Encrypt 用的是標準程式庫 (standard library) 中的 string 不是嗎?所以我們先來介紹一下 QString 吧!


中英文術語對照
變數成員variable member
函數成員function member
建構子constructor
函數function
參數parameter
關鍵字keyword
型態type
標準函數庫standard library


您可以繼續參考
GUI 篇


相關目錄
回 C++ 入門指南
回 C++ 教材目錄
回首頁


參考資料
Qt Developer Network
Signals & Slots

沒有留言: