漫談QWidget及其衍生類別(二)__Qt

來源:互聯網
上載者:User

上一部分漫談QWidget及其衍生類別(一) 介紹了QWidget及其衍生類別,分:視窗、普通控制項兩種類型(其實有個Qt::SubWindow沒有提,不過本系列中也沒有介紹它的打算,因為我不熟)。

本文接下來試圖看看 QLayout 與視窗的幾何尺寸控制。

注意:本文只是試圖解釋,QLayout其實沒有任何神秘的東西,它所有的功能離開它你也都可以做。但這並不是鼓勵大家不使用QLayout。

始終記住一點:要改變一個Widget的大小,只有move()、resize()、setGeometry()這3個東西可用,當然,對於帶裝飾器的最上層視窗,你還可以通過滑鼠等改變大小或移動視窗位置(但這個不在本文討論範圍內)。 幾何尺寸


一個QWidget 或其衍生類別 放置到什麼位置。 需要佔多大的地盤。

對於一個視窗(Window)來說,還要區分: 帶視窗裝飾器後的位置和大小 不帶裝飾器(用戶端區域。繪圖區域。)的位置和大小

看起來還蠻複雜的哈,列個表看看。

frameGeometry()

幾何尺寸(位置+大小)

對於視窗,包含視窗裝飾器

x()
y()
pos()

只包含位置資訊(左上方座標)

move()

只移動位置

geometry()

幾何尺寸(位置+大小)

不包含視窗裝飾器

width()
height()
rect()
size()

只包含大小資訊

setGeometry()

改變 位置+大小

resize()

只改變大小

關鍵記住一點:要程式內改變一個Widget的大小,只有move、resize、setGeometry這3個東西可用。不要被QLayout幹擾,它一點都不神秘,它也只能老老實實去調用這類函數。 例子

用個例子看看吧,如果 在一個 400X400 的Widget上,放置很多其他Widget(比如64個 45X45 的按鈕)

#include <QtGui/QApplication>#include <QtGui/QPushButton>int main(int argc, char *argv[]){    QApplication a(argc, argv);    QWidget widget;    widget.setGeometry(100, 100, 400, 400);    for (int i=0; i<8; ++i) {        for (int j=0; j<8; ++j) {            QPushButton * btn = new QPushButton(QString("(%1,%2)").arg(i).arg(j), &widget);            btn->setGeometry(i*50, j*50, 45, 45);        }    }    widget.show();    return a.exec();}

只需要挨個設定一下幾何尺寸,似乎也不複雜嘛。是吧。 困難是什麼呢。 如果我們用滑鼠拖動來改變視窗Widget的大小(有裝飾器,可以拖動),它上面的這些按鈕卻不會動(我們前面的很黑體字提到的哈)。介面將很難看。

其實這也不是大問題,我們只需要在子類化QWidget,覆蓋(override)它的resizeEvent()函數

void Widget::resizeEvent(QResizeEvent *){}

在這兒重新設定它上面的按鈕的位置和大小就行了。 考慮一個問題,我們如何知道一個widget用多大的大小合適呢。

這是個大問題,單一的widget還好解決,比如一個按鈕,你可以根據文字、按鈕樣式等等計算一個大小。可是對於複合的widget:比如我們例子中的widget中有64個按鈕,如果再將這樣的64個widget放於另外一個widget中,會怎麼樣。

沒有什麼好辦法,仍然是需要我們一個一個進行計算。其實不是太難,但是操作特別繁雜。 再考慮一個問題,如果我們改變一個按鈕上的文字,按鈕的最佳尺寸要變化,如何處理。

只能是按鈕通知其parent(通過LayoutRequest事件),而後parent重新排布子控制項,以獲得最佳顯示效果。

接下來,我們看看 QLayout 是如何解決這三個問題的。 QLayout

layout 做哪些事情呢。

初始放置

將子widget一個一個放置到父widget上

layout 計算各個子widget大小,並調用setGeometry() 來設定

響應父widget變化

父widget大小變化時,子widget相應變化

layout 通過監聽父widget的QResizeEvent事件來實現

響應子widget變化

子widget的最佳大小變化時
(比如給按鈕設定新的Text)

讓父物件的layout 重新計算幾何尺寸

QResizeEvent

當一個widget的大小變化後,會產生QResizeEvent事件(這時widget所關聯Layout就開始重新計算嘍...)。

我們知道,事件都是通過QWidget::event()派發的:

bool QWidget::event(QEvent *event){    switch (event->type()) {    case QEvent::MouseMove:        mouseMoveEvent((QMouseEvent*)event);        break;...    case QEvent::Move:        moveEvent((QMoveEvent*)event);        break;    case QEvent::Resize:        resizeEvent((QResizeEvent*)event);        break;...

但是,Qt對QLayout有特殊照顧,在事件到達接收者的event()函數之前,先送到了接收者對應的layout中:

bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e){...    if (receiver->isWidgetType()) {        QWidget *widget = static_cast<QWidget *>(receiver);        if (QLayout *layout=widget->d_func()->lay

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.