Qt訊號槽機制的簡單例子

來源:互聯網
上載者:User

回到QT,先在VS中建立一個QT Application,項目裡面有幾個目錄:

1、Form Files目錄,它裡面放的是使用QT designer製作的基於XML的布局檔案,雙擊它就會自動進入QT designer。

2、Generated Files目錄,它裡面放的是一些臨時產生的檔案,這些檔案用來處理QT的訊號和槽等機制。

3、Resource Files目錄,它裡面放的是基於XML的資源檔,你可以在表單裡面使用它們。

4、Header Files和Source Files這兩個和VS預設是一樣的。

理解了目錄結構之後,先來試著寫一個Hello World,先把除了main.cpp之外的所有檔案移除(使用QT designer會提高製作效率,但是會讓QT入門門檻變高)!開啟main.cpp,僅保留以下代碼:

#include <QtGui/QApplication>  
int main(int argc, char *argv[])  
 
{  
         QApplication a(argc, argv);        
         return a.exec();  

編譯通過。運行沒有任何反應,因為還沒有往裡面增加任何東西。

在代碼中,Main函數是C語言的入口,之後申請的QApplication用來管理控制流程和主要設定,這是核心,一定要保留。

按鈕是GUI中最基本的一個控制項,先看看怎麼增加一個按鈕。使用按鈕控制項必須先包含標頭檔:

#include <QtGui/QPushButton>

然後在QApplication a(argc, argv);與return a.exec();中間插入下面代碼:

QPushButton button("HELLO");  
 
button.setGeometry(100,100,300,300);  
 
button.show(); 

代碼第一行是申請一個按鈕,並把按鈕的Caption標題設為HELLO,第二行表示這個按鈕出現在螢幕座標(100,100)的位置,寬高為(300,300),最後一行是顯示這個按鈕,你可以嘗試把它去掉看看效果(官方助手裡有QPushButton的更多資料,請自行查看)。

編譯出來,發現螢幕上出現一個框,框裡面有一個按鈕,按鈕可以點擊,但是沒有任何反應,因為還沒有為這個按鈕增加任何的槽(Slot)。

在MFC對控制項的處理一般是通過事件機制,而在QT中是使用訊號(Signal)和槽(Slot)機制,其實你也可以把它理解為事件機制。

簡單理解訊號其實就是輸入,而槽就是輸出,拿按鈕打比方,在一次點擊中,這個點擊,就是一個訊號,而點擊後的反饋,就是槽。

每一個控制項都擁有一些預設的Signal和Slot,這些都可以在官方提供的助手中查看。

綁定Signal和slot是使用靜態函數connect。函數原型是:

Bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection ) 

其中sender是寄件者,而receiver是接收者,signal是訊號,而method就是slot,type裡面提供了幾種綁定方式,可以詳細查看助手。

         先看一個例子,在上面代碼中加入點擊按鈕後關閉應用程式的效果。很簡單,只需要在
button. setGeometry(100,100,300,300);

後面加入

QObject::connect(&button, SIGNAL(clicked()), &a, SLOT(quit()));

編譯運行,點擊後表單關閉。

這是使用預設槽的例子,有時候需要點擊按鈕之後執行自訂的效果,那麼就需要使用自訂槽了。

下面是一個使用自訂Slot的例子,滑鼠點擊按鈕之後,文字框文字會改變。

先加入一個QLabel控制項,你先加入標頭檔:

 
#include <QtGui/QLabel>

然後在connect前加入

QLabel label("World");

label.setGeometry(50,50,300,300);
 

先嘗試編譯一下,結果label沒有出現在表單裡面!它當然不會出現在表單裡面,因為我們只是對Button使用了Show()函數,嘗試加入label.show(),結果出現了兩個表單,一個裡面有按鈕,另一個裡面有一個label。那麼怎麼把它們放在一起呢

通過上面的測試發現,調用一次show就會產生一個視窗,那麼是不是只調用一次show就行了?把函數裡面代碼改為:

QApplication a(argc, argv);  
 
QWidget window;  
 
QPushButton button("HELLO");  
 
button.setGeometry(100,100,300,300);  
 
QLabel label("World");  
 
label.setGeometry(50,50,300,300);  
 
QHBoxLayout layout;  
 
Layout.addWidget(&button);  
 
Layout.addWidget(&label);  
 
QObject::connect(&button, SIGNAL(clicked()), &window, SLOT(close()));  
 
window.setLayout(&layout);  
 
window.show();         
 
 return a.exec();

附上此時的標頭檔列表:

#include <QtGui/QPushButton>

#include <QtGui/QApplication>

#include <QtGui/QLabel>

#include <QtGui/QHBoxLayout>

#include <QtGui/QWidget>
 

一開始,我就申請了一個QWidget,QWidget類是QT中所有使用介面物件的基類,它本身並沒有什麼實際意義,在這裡你可以把它看成一個表單容器,然後又添加了一個

QHBoxLayout layout; QHBoxLayout這是個可以對子widget進行特定布局的控制項,通過它可以把按鈕和label並排,之後把表單的layout設為指定的layout,然後調用show()。

調試運行,終於兩個控制項都出現了。

回到之前的話題,自訂槽。在QT中所有自訂槽都需要先編譯成moc,才可以被使用。不過你放心,這個過程由QT自動完成,當然你也可以手動進行編譯,QT的Bin目錄裡面有moc.exe,參照說明進行使用。

你應該可以看到我已經偷偷把按鈕的點擊訊號轉向了表單的close槽。為什麼要這樣做呢,因為我們需要把自訂槽函數定義放在標頭檔裡。

第一步,先把window封裝起來,我建立一個MainWidget類,繼承自QWidget類,類的標頭檔如下:

view plaincopy to clipboardprint?
#ifndef _MAIN_WIDGET_H_ 
 
#define _MAIN_WIDGET_H_ 
 
#include <QtGui/QLabel> 
 
#include <QtGui/QHBoxLayout> 
 
#include <QtGui/QWidget> 
 
#include <QtGui/QPushButton>  
 
class MainWidget: public QWidget  
 
{  
 
public:  
 
         MainWidget();  
 
         ~MainWidget();  
 
   
 
protected:                   
 
   
 
private:      
 
         QLabel*                               m_pLabel;  
 
         QPushButton*          m_pButton;  
 
         QHBoxLayout*                   m_pLayout;  
 
}; 
 
#endif  
 
CPP如下: 
 
#include "MainWidget.h"  
 
MainWidget::MainWidget()  
 
{  
 
         m_pLabel = new QLabel("World");  
 
         m_pLabel ->setGeometry(50,50,300,300);  
 
         m_pButton = new QPushButton ("HELLO");  
 
         m_pButton ->setGeometry(100,100,300,300);  
 
         m_pLayout = new QHBoxLayout();  
 
         m_pLayout -> addWidget(m_pButton);  
 
         m_pLayout -> addWidget(m_pLabel);  
 
         connect(m_pButton, SIGNAL(clicked()), this, SLOT(close()));  
 
         setLayout(m_pLayout);  
 
}  
 
MainWidget::~MainWidget()  
 
{  
 

Main.cpp改為:

#include <QtGui/QApplication> 
 
#include "MainWidget.h"  
 
int main(int argc, char *argv[])  
 
{  
 
         QApplication a(argc, argv);  
 
         MainWidget window;        
 
         window.show();         
 
         return a.exec();  
 
}

編譯運行,結果和上次一樣。

接下來申請一個自訂Slot,首先在標頭檔public:前加入宏

Q_OBJECT;

只有加入了Q_OBJECT,你才能使用QT中的signal和slot機制。這點很重要,不然你編譯的時候會報“找不到slot”的錯誤。

然後在protected:  前加入:
private slots:

void                SetText ();
 

slot同樣也分private、public、protected,意義和c++一樣。

CPP中加入相應執行:

void MainWidget:: SetText ()

{

         m_pLabel -> setText("Test");

}
 

把connect改成: 
connect(m_pButton, SIGNAL(clicked()), this, SLOT(SetText ()));

編譯運行,這時點擊按鈕就會改變文字了。就這麼簡單。

訊號也可以自訂,不過訊號自訂相對來說用武之地稍微小一點,定義的方式和slot定義差不多,都得在標頭檔中定義,舉個例子:點擊按鈕後文本改變,觸發一個新訊號,這個訊號會把文字又變回來。

在標頭檔中加入:
signals:

     void TextChanged ();
 

再增加一個Slot用來對這個訊號進行反饋。在private slots:後加入

void                              RecoverText ();

CPP中加入執行:

void MainWidget::RecoverText()

{

         m_pLabel -> setText("Hello");

}
 

注意訊號是不需要加執行代碼。

然後修改SetText()函數加入觸發新訊號的代碼:

emit TextChanged();

最後加入新的connect:

 
connect(this, SIGNAL(TextChanged()), this, SLOT(RecoverText()));

編譯運行,結果和我們想要的一樣。

註:訊號和槽都是可以有參數的。

有關QT的基礎知識就介紹到這裡,具體控制項的使用方法,請自行參考助手。

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/pizi0475/archive/2010/05/19/5609474.aspx

 

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/tulun/archive/2010/05/31/5635782.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.