[轉]QT的自動滾動區QScrollArea的用法,圖文詳解

本文轉載於:QT的自動滾動區QScrollArea的用法,圖文詳解

ScrollArea屬於控件容器類,可以直接在ui中拖出來。

對於QScrollArea,最難搞懂的就是:如何控制它,才能讓它在我們想要出現滾動條的時候出現滾動條。

我們拖入一個QScrollArea,再向他裏面拖入4個button,觀察信息如下:

可以發現,4個button並不是直接位於QScrollArea中的,而是位於它的成員scorllAreaWidgetContents中的,這個成員的類型也是控件類型QWidget,也就是說,QScrollArea這個容器本身就套了兩層,我們放入的按鈕等控件,都處在scrllAreaWidgetContents層,下文中我把QScrollArea.widget統一稱之爲“內部容器”或者"內容層",內部容器是QScrollArea這個控件的子控件。

"內容層"相當於一塊很大的幕布,按鈕、label等控件都被繪製在了幕布上,而QScrollArea相當於一個小窗口,透過這個小窗口我們看一看到幕布上的一小部分內容,拖動滾動條相當於在窗口後面移動幕布,這樣我們就能透過窗口看到幕布上不同位置的內容。

這個幕布本質上就是一個QWidget,如果QScrollArea是從UI設計師界面拖出來的,那麼QT會自動爲我們創建這個幕布,如果你是用代碼new出來的QScrollArea,那麼不要忘記同時new一個幕布widget,並通過QScrollArea::setWidget(QWidget *)把幕布和QScrollArea關聯起來。

這裏有一個坑,如果你寫了一個功能更強的QScrollArea的子類,假設叫QScrollAreaEx(裏面自帶幕布,幕布中自帶一些按鈕什麼的),在ui設計師界面把QScrollArea提升爲QScrollAreaEx的時候,你會發現,按鈕並沒有顯示出來,why?因爲QT自動生成的ui代碼中,new了一個幕布控件,並把這個空的幕布賦給了QScrollAreaEx對象,這真是太坑了。解決方案有兩種,①自己用代碼new QScrollAreaEx,②在ui中拖出一個非QScrollArea的QWidget控件,然後提升爲QScrollAreaEx。

 

 

一旦理解了幕布和觀察窗口的關係,就能很容易的總結出QScrollArea的標準編程步驟,分這麼幾種情況:

    情形1,純代碼實現

(1)new QscrollArea
(2)new 內部的幕布容器
(3)new 佈局,例如網格佈局QGridLayout(前3步不分先後順序)或者你想用的其他佈局
(4)向佈局中添加你想要的控件(這一步必須位於步驟3之後,這不是廢話嗎)
(5)關聯"幕布控件"和"佈局"(如果在創建佈局時,就把佈局構造在了幕布控件中,那麼這一步就省了)
(6)給QScroolArea設置幕布,也即調用QScrollArea::setWidget(QWidget *),這一步必須位於步驟4、5之後。

    情形2,QScrollArea是直接在ui裏拖出來的,滾動區裏面的控件是代碼new的,那麼編程步驟如下:

只做上一種情形的步驟(3)(4)(5)即可。

    情形3,QScrollArea和它裏面的控件都是直接在ui裏拖出來的

這種情形不用寫代碼,只要在滾動區域把控件擺放好,然後使用任意一種佈局即可,如下2圖所示:

 

   一句話總結何時出現滾動條:

只要幕布控件scorllAreaWidgetContents的大小超過了QScrollArea的大小,就會自動出現滾動條;如果幕布比觀察窗口還小,那就不會出現滾動條。

最後再看幾個實例,

我給scorllAreaWidgetContents成員設置寬高最小值爲500*1000,這麼高的scorllAreaWidgetContents,顯然QScrollArea在高度上是無法容納下的。實際上,看效果發現,還沒有運行程序,就已經有滾動條了:

 

我們運行一下程序,然後把窗口縮小,看看是不是當窗口<scorllAreaWidgetContents最小值500*1000時,會自動出現水平滾動條。看下圖發現,並沒有出現我們期望的效果。

原因就是,水平滾動條,只有當QScrollArea<內部的QWidget時,纔會出現,顯然上圖中,QScrollArea雖然沒顯示全,但是QScrollArea的寬度仍然保持原值,只是被遮住了而已。要想使QScrollArea的寬度變小,要麼通過程序直接修改,要麼通過設置佈局,使QScrollArea的寬度隨窗體的寬度減小而減小。我們這裏就簡單一點,直接給窗體設置網格佈局:

使得QScrollArea的大小受窗體大小驅動。運行起來,再看下效果:

再補充幾點:

內部的小QWidget與QScrollArea的關係,就像是給QScrollArea設置了網格佈局,然後把小QWidget放進了這個佈局中,如果給小QWidget設置的最大寬高<QScrollArea的實時大小,那麼QScrollArea會顯示出空白,而空白部分是無法放置/顯示我們自己拖入的控件的,如下圖:

技巧:

通過上述操作,我們知道了,我們可以通過設置內部小QWidget的寬、高最小值,來讓外部QScrollArea適時的出現滾動條,那麼到底把小QWidget的寬、高最小值設置爲多少合適呢?

答案是顯然的:把小QWidget的寬、高最小值設置爲剛好能容納內部的按鈕等控件,這樣看起來最舒服。難道我要先計算或者觀察一下按鈕等控件佔用的面積之後,才能去設置小QWidget的寬、高最小值嗎?

這樣做太費勁了,我們肯定不會去這樣做,除非是用ui設計師拖控件時,所見即所得,才無需計算小QWidget的寬、高最小值。用代碼寫界面時,最好的做法是:

1、向小QWidget中添加按鈕等控件時,隨着添加的按鈕增多,小QWidget自動變大,顯然用QGridLayout來做就能實現這個自動增大這個需求。自動增大也只是出現創建內部容器階段,一旦內部容器和佈局、佈局內的控件都創建和添加完畢,後續即使再向佈局中添加控件,內部容器也不會自動增大了,這時只有靠setGeometry或者resize手動修改內部容器的大小了。

2、添加完控件後,手動調用一下adjustSize函數,該函數會根據所有子控件的大小之和,來調整父控件的大小。

步驟如下:先在ui中拖入一個QScrollArea控件,名字爲scrollArea,然後添加代碼:

   

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
     
        QGridLayout *pLayout = new QGridLayout();//網格佈局
        for(int i = 0; i < 100; i++)
        {
            QPushButton *pBtn = new QPushButton();
            pBtn->setText(QString("按鈕%1").arg(i));
            pBtn->setMinimumSize(QSize(60,30));   //width height
            pLayout->addWidget(pBtn);//把按鈕添加到佈局控件中
        }
        ui->scrollArea->widget()->setLayout(pLayout);//把佈局放置到QScrollArea的內部QWidget中
    }


————————————————
版權聲明:本文爲CSDN博主「qq_610642」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_31073871/article/details/83117430

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章