回到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