鍍金池/ 教程/ C/ 組件布局
Qt 容器和算法拾遺
自定義 model 之一
反走樣
Hello, world!
Qt 容器類之關(guān)聯(lián)存儲容器
QStringListModel
拖放技術(shù)之一
狀態(tài)欄
QTreeWidget
拖放技術(shù)之二
通用算法
event()
Qt 學(xué)習(xí)之路(18): Qt 標(biāo)準(zhǔn)對話框之 QInputDialog
Qt 容器類之遍歷器和隱式數(shù)據(jù)共享
QListWidget
Meta-Object 系統(tǒng)
事件接收與忽略
Qt 學(xué)習(xí)之路(tip): parent 參數(shù)
Qt 標(biāo)準(zhǔn)對話框之 QColorDialog
QPainter(續(xù))
國際化(下)
漸變填充
自定義委托
創(chuàng)建 shared library
model-view 架構(gòu)
Graphics View Framework
自定義拖放數(shù)據(jù)對象
QSortFilterProxyModel
國際化(上)
組件布局
自定義 Model 之三
事件過濾器
QDirModel
Hello, world!(續(xù))
Qt 標(biāo)準(zhǔn)對話框之 QFileDialog
自定義 model 之二
深入了解信號槽
坐標(biāo)變換
剪貼板操作
QTableWidget
QByteArray 和 QVariant
創(chuàng)建一個(gè)對話框(下)
Qt 學(xué)習(xí)之路(32): 一個(gè)簡易畫板的實(shí)現(xiàn)(Graphics View)
文本文件讀寫
自定義事件
編寫跨平臺的程序
MainWindow
初探信號槽
Qt 學(xué)習(xí)之路(17): Qt 標(biāo)準(zhǔn)對話框之 QMessageBox
繪圖設(shè)備
菜單和工具條(續(xù))
二進(jìn)制文件讀寫
QString
事件(event)
菜單和工具條
QPainter
Qt 容器類之順序存儲容器
進(jìn)程間交互
API 文檔的使用
創(chuàng)建一個(gè)對話框(上)
一個(gè)簡易畫板的實(shí)現(xiàn)(QWidget)

組件布局

同 Swing 類似,Qt 也提供了幾種組件定位的技術(shù)。其中就包括絕對定位和布局定位。

顧名思義,絕對定位就是使用最原始的定位方法,給出這個(gè)組件的坐標(biāo)和長寬值。這樣,Qt 就知道該把組件放在哪里,以及怎么設(shè)置組件的大小了。但是這樣做的一個(gè)問題是,如果用戶改變了窗口大小,比如點(diǎn)擊了最大化或者拖動(dòng)窗口邊緣,這時(shí),你就要自己編寫相應(yīng)的函數(shù)來響應(yīng)這些變化,以避免那些組件還只是靜靜地呆在一個(gè)角落。或者,更簡單的方法是直接禁止用戶改變大小。

不過,Qt 提供了另外的一種機(jī)制,就是布局,來解決這個(gè)問題。你只要把組件放入某一種布局之中,當(dāng)需要調(diào)整大小或者位置的時(shí)候,Qt 就知道該怎樣進(jìn)行調(diào)整。這類似于 Swing 的布局管理器,不過 Qt的布局沒有那么多,只有有限的幾個(gè)。

來看一下下面的例子:

#include <QtGui/QApplication> 
#include <QtGui/QWidget> 
#include <QtGui/QSpinBox> 
#include <QtGui/QSlider> 
#include <QtGui/QHBoxLayout> 

int main(int argc, char *argv[]) 
{ 
        QApplication app(argc, argv); 
        QWidget *window = new QWidget; 
        window->setWindowTitle("Enter your age"); 

        QSpinBox *spinBox = new QSpinBox; 
        QSlider *slider = new QSlider(Qt::Horizontal); 
        spinBox->setRange(0, 130); 
        slider->setRange(0, 130); 

        QObject::connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int))); 
        QObject::connect(spinBox, SIGNAL(valueChanged(int)), slider, SLOT(setValue(int))); 
        spinBox->setValue(35); 

        QHBoxLayout *layout = new QHBoxLayout; 
        layout->addWidget(spinBox); 
        layout->addWidget(slider); 
        window->setLayout(layout); 

        window->show(); 

        return app.exec(); 
}

這里使用了兩個(gè)新的組件:QSpinBox 和 QSlider,以及一個(gè)新的頂級窗口 QWidget。QSpinBox 是一個(gè)有上下箭頭的微調(diào)器,QSlider 是一個(gè)滑動(dòng)桿,只要運(yùn)行一下就會明白到底是什么東西了。

代碼并不是那么難懂,還是來簡單的看一下。首先創(chuàng)建了一個(gè) QWidget 的實(shí)例,調(diào)用 setWindowTitle 函數(shù)來設(shè)置窗口標(biāo)題。然后創(chuàng)建了一個(gè) QSpinBox 和 QSlider,分別設(shè)置了它們值的范圍,使用的是 setRange 函數(shù)。然后進(jìn)行信號槽的鏈接。這點(diǎn)后面再詳細(xì)說明。然后是一個(gè)QHBoxLayout,就是一個(gè)水平布局,按照從左到右的順序進(jìn)行添加,使用 addWidget 添加好組件后,調(diào)用 QWidget 的 setLayout 把 QWidget 的 layout 設(shè)置為我們定義的這個(gè) Layout,這樣,程序就完成了!

編譯運(yùn)行一下,可以看到效果:

http://wiki.jikexueyuan.com/project/learn-road-qt/images/9.png" alt="" />

如果最大化的話:

http://wiki.jikexueyuan.com/project/learn-road-qt/images/10.png" alt="" />

雖然我并沒有添加任何代碼,但是那個(gè) layout 就已經(jīng)明白該怎樣進(jìn)行布局。

或許你發(fā)現(xiàn),那兩個(gè)信號槽的鏈接操作會不會產(chǎn)生無限遞歸?因?yàn)?steValue 就會引發(fā) valueChanged信號!答案是不會。這兩句語句實(shí)現(xiàn)了,當(dāng) spinBox 發(fā)出 valueChanged 信號的時(shí)候,會回調(diào)slider 的 setValue,以更新 slider 的值;而 slider 發(fā)出 valueChanged 信號的時(shí)候,又會回調(diào) slider 的 setValue。但是,如果新的 value 和舊的 value 是一樣的話,是不會發(fā)出這個(gè)信號的,因此避免了無限遞歸。

迷糊了吧?舉個(gè)例子看。比如下面的 spinBox->setValue(35)執(zhí)行的時(shí)候,首先,spinBox 會將自己的值設(shè)為35,這樣,它的值與原來的不一樣了(在沒有 setValue 之前的時(shí)候,默認(rèn)值是0),于是它發(fā)出了 valueChanged 信號。slider 接收到這個(gè)信號,于是回調(diào)自己的 setValue 函數(shù),將它的值也設(shè)置成35,它也發(fā)出了 valueChanged 信號。當(dāng)然,此時(shí) spinBox 又收到了,不過它發(fā)現(xiàn),這個(gè)35和它本身的值是一樣的,于是它就不發(fā)出信號,所以信號傳遞就停止了。

那么,你會問,它們是怎么知道值的呢?答案很簡單,因?yàn)槟愕男盘柡筒鄱冀邮芰艘粋€(gè)int參數(shù)!新的值就是通過這個(gè)進(jìn)行傳遞的。實(shí)際上,我們利用Qt的信號槽機(jī)制完成了一個(gè)數(shù)據(jù)綁定,使兩個(gè)組件或者更多組件的狀態(tài)能夠同步變化。

Qt 一共有三種主要的 layout,分別是:

QHBoxLayout- 按照水平方向從左到右布局;

QVBoxLayout- 按照豎直方向從上到下布局;

QGridLayout- 在一個(gè)網(wǎng)格中進(jìn)行布局,類似于 HTML 的 table。

layout 使用 addWidget 添加組件,使用 addLayout 可以添加子布局,因此,這就有了無窮無盡的組合方式。

我是在 Windows 上面進(jìn)行編譯的,如果你要是在其他平臺上面,應(yīng)用程序就會有不同的樣子:

http://wiki.jikexueyuan.com/project/learn-road-qt/images/11.png" alt="" />

還記得前面曾經(jīng)說過,Qt 不是使用的原生組件,而是自己繪制模擬的本地組件的樣子,不過看看這個(gè)截圖,它模擬的不能說百分百一致,也可說是惟妙惟肖了… :)

本文出自 “豆子空間” 博客,請務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031