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