QT的自动滚动区QScrollArea的用法,图文详解
轉(zhuǎn)自 https://blog.csdn.net/qq_31073871/article/details/83117430
QScrollArea屬于控件容器類,可以直接在ui中拖出來。
對(duì)于QScrollArea,最難搞懂的就是:如何控制它,才能讓它在我們想要出現(xiàn)滾動(dòng)條的時(shí)候出現(xiàn)滾動(dòng)條。
我們拖入一個(gè)QScrollArea,再向他里面拖入4個(gè)button,觀察信息如下:
可以發(fā)現(xiàn),4個(gè)button并不是直接位于QScrollArea中的,而是位于它的成員scorllAreaWidgetContents中的,這個(gè)成員的類型也是控件類型QWidget,也就是說,QScrollArea這個(gè)容器本身就套了兩層,我們放入的按鈕等控件,都處在scrllAreaWidgetContents層,下文中我把QScrollArea.widget統(tǒng)一稱之為“內(nèi)部容器”,內(nèi)部容器是QScrollArea這個(gè)控件的子控件。
補(bǔ)充一點(diǎn),內(nèi)層的這個(gè)scrllAreaWidgetContents,我們可以更換掉它,方法就是QScrollArea::setWidget(QWidget *),如果scrollArea控件是用鼠標(biāo)拖出來的,那么QT會(huì)自動(dòng)為我們new一個(gè)內(nèi)部容器,如果scrollArea控件是用代碼創(chuàng)建的,那么不忘忘了為這個(gè)滾動(dòng)區(qū)創(chuàng)建內(nèi)部容器。
幫助文檔還指出,setWidget應(yīng)當(dāng)在“把想加的控件都加到內(nèi)部容器”之后再調(diào)用,否則會(huì)無法顯示(然而,我測(cè)試發(fā)現(xiàn),幫助說的不對(duì),即使我們?cè)趕etWidget之前沒有給內(nèi)部容器設(shè)置布局也不要緊,只要在setWidget之后,內(nèi)部容器調(diào)用一下adjustSize,就可以把內(nèi)部容器的控件顯示出來,當(dāng)然,為了保險(xiǎn)起見,或者后續(xù)程序兼容性起見,還是按照幫助文檔來做吧)。
總結(jié)一下滾動(dòng)區(qū)的標(biāo)準(zhǔn)編程步驟:
(1)new QscrollArea
(2)new 內(nèi)部容器
(3)new 布局,例如網(wǎng)格布局QGridLayout(前3步不分先后順序)
(4)向布局中添加你想要的控件(這一步必須位于步驟3之后,這不是廢話嗎)
(5)關(guān)聯(lián)"內(nèi)部容器"和"布局"(如果在創(chuàng)建布局時(shí),就把布局構(gòu)造在了內(nèi)部容器中,那么這一步就省了)
(6)關(guān)聯(lián)"內(nèi)部容器"和"滾動(dòng)區(qū)",也即調(diào)用QScrollArea::setWidget(QWidget *),這一步必須位于步驟4、5之后。
?
?
一句話總結(jié)何時(shí)出現(xiàn)滾動(dòng)條:
只要QScrollArea的尺寸 < 內(nèi)部容器的尺寸,就會(huì)自動(dòng)出現(xiàn)滾動(dòng)條。下面舉個(gè)具體的例子:
程序初始時(shí)我們通過setGeometry設(shè)置內(nèi)部容器的尺寸為100X100,QScrollArea放置在主界面的布局中,也即QScrollArea的尺寸是隨著用戶鼠標(biāo)拖動(dòng)窗口變化而變化的,那么當(dāng)用戶拖大窗口時(shí),QScrollArea也變得很大,而內(nèi)部容器還是100X100,這時(shí),滾動(dòng)條就消失了;如果用戶用鼠標(biāo)縮小了窗口,QScrollArea也隨之變的很小了,而內(nèi)部容器還是100X100,QScrollArea就會(huì)自動(dòng)出現(xiàn)滾動(dòng)條。
記住一句話,除非你在程序運(yùn)行時(shí)修改了內(nèi)部容器的大小,否則,內(nèi)部容器將一直保持它初始的大小。那么
?
?
下面講如何控制滾動(dòng)條何時(shí)出現(xiàn)?
有了上面的分析,我們已經(jīng)知道了QScrollArea有兩層,QScrollArea本身是個(gè)QWidget,它內(nèi)部又套了一個(gè)小QWidget。在默認(rèn)情況下,內(nèi)部的這個(gè)小QWidget,也即scorllAreaWidgetContents,它的大小總是等于外部QWidget(也即QScrollArea)的大小。除非我們給scorllAreaWidgetContents設(shè)置了寬高的最小值,這時(shí),當(dāng)QScrollArea的寬或高,一旦小于scorllAreaWidgetContents的寬或高,就會(huì)出現(xiàn)滾動(dòng)條。
這個(gè)scorllAreaWidgetContents是從哪來的?查看QT自動(dòng)生成的ui代碼(也即:ui->setupUi(this)函數(shù))可見,它是在QScrollArea構(gòu)造完成之后,再被new出來的,然后調(diào)用了QScrollArea::setWidget()。這一點(diǎn)對(duì)于我們編程非常重要,否則一不小心就中了坑,假設(shè)我們自己繼承QScrollArea寫了一個(gè)新的子類,在子類的構(gòu)造函數(shù)中我們通過QScrollArea::setWidget()設(shè)置好了自己的小QWidget,然后在ui中把QScrollArea提升為自己寫的這個(gè)子類,這時(shí)就扯淡了,我們?cè)谧宇悩?gòu)造函數(shù)中為小QWidget添加的控件都沒有顯示出來,因?yàn)镼T自作主張,在我們自己的構(gòu)造函數(shù)執(zhí)行完之后,重新new了小QWidget,并通過setWidget函數(shù)設(shè)置給了這個(gè)子類!這真是太坑了。如果你想通過ui提升的方式來使用自己寫的子類,那么請(qǐng)你在ui拖入一個(gè)Frame容器或者widget容器等等進(jìn)行提升,反正不要用拖入的QScrollArea容器進(jìn)行提升。如果你非得想用QScrollArea容器進(jìn)行提升,那么你想在QScrollArea的內(nèi)部容器中添加控件時(shí),請(qǐng)不要把添加控件的代碼寫在QScrollArea子類的構(gòu)造函數(shù)中。
下面繼續(xù)研究滾動(dòng)條問題。
直接看例子,我給scorllAreaWidgetContents成員設(shè)置寬高最小值為500*1000,這么高的scorllAreaWidgetContents,顯然QScrollArea在高度上是無法容納下的。實(shí)際上,看效果發(fā)現(xiàn),還沒有運(yùn)行程序,就已經(jīng)有滾動(dòng)條了
我們運(yùn)行一下程序,然后把窗口縮小,看看是不是當(dāng)窗口<scorllAreaWidgetContents最小值500*1000時(shí),會(huì)自動(dòng)出現(xiàn)水平滾動(dòng)條。看下圖發(fā)現(xiàn),并沒有出現(xiàn)我們期望的效果。
原因就是,水平滾動(dòng)條,只有當(dāng)QScrollArea<內(nèi)部的QWidget時(shí),才會(huì)出現(xiàn),顯然上圖中,QScrollArea雖然沒顯示全,但是QScrollArea的寬度仍然保持原值,只是被遮住了而已。要想使QScrollArea的寬度變小,要么通過程序直接修改,要么通過設(shè)置布局,使QScrollArea的寬度隨窗體的寬度減小而減小。我們這里就簡單一點(diǎn),直接給窗體設(shè)置網(wǎng)格布局,使得QScrollArea的大小受窗體大小驅(qū)動(dòng)。運(yùn)行起來,再看下效果:
再補(bǔ)充幾點(diǎn):
內(nèi)部的小QWidget與QScrollArea的關(guān)系,就像是給QScrollArea設(shè)置了網(wǎng)格布局,然后把小QWidget放進(jìn)了這個(gè)布局中,如果給小QWidget設(shè)置的最大寬高<QScrollArea的實(shí)時(shí)大小,那么QScrollArea會(huì)顯示出空白,而空白部分是無法放置/顯示我們自己拖入的控件的,如下圖:
如果我們不給小QWidget設(shè)置寬高最大值,那么它的寬width將滿足:
它的高也有與之相同的規(guī)律。
知道了原理,不論是用UI設(shè)計(jì)器來做界面,還是直接用代碼來做界面,就都不是問題了。
?
技巧:
通過上述操作,我們知道了,我們可以通過設(shè)置內(nèi)部小QWidget的寬、高最小值,來讓外部QScrollArea適時(shí)的出現(xiàn)滾動(dòng)條,那么到底把小QWidget的寬、高最小值設(shè)置為多少合適呢?
答案是顯然的:把小QWidget的寬、高最小值設(shè)置為剛好能容納內(nèi)部的按鈕等控件,這樣看起來最舒服。難道我要先計(jì)算或者觀察一下按鈕等控件占用的面積之后,才能去設(shè)置小QWidget的寬、高最小值嗎?
這樣做太費(fèi)勁了,我們肯定不會(huì)去這樣做,除非是用ui設(shè)計(jì)師拖控件時(shí),所見即所得,才無需計(jì)算小QWidget的寬、高最小值。用代碼寫界面時(shí),最好的做法是:
1、向小QWidget中添加按鈕等控件時(shí),隨著添加的按鈕增多,小QWidget自動(dòng)變大,顯然用QGridLayout來做就能實(shí)現(xiàn)這個(gè)自動(dòng)增大這個(gè)需求。自動(dòng)增大也只是出現(xiàn)創(chuàng)建內(nèi)部容器階段,一旦內(nèi)部容器和布局、布局內(nèi)的控件都創(chuàng)建和添加完畢,后續(xù)即使再向布局中添加控件,內(nèi)部容器也不會(huì)自動(dòng)增大了,這時(shí)只有靠setGeometry手動(dòng)修改內(nèi)部容器的大小了。
2、添加完控件后,手動(dòng)調(diào)用一下adjustSize函數(shù),該函數(shù)會(huì)根據(jù)所有子控件的大小之和,來調(diào)整父控件的大小。
步驟如下:先在ui中拖入一個(gè)QScrollArea控件,名字為scrollArea,然后添加代碼:
?
?根據(jù)原著者的描述,轉(zhuǎn)載人補(bǔ)充如下代碼,展示在不使用ui拖拽的情況下,實(shí)現(xiàn)滾動(dòng)條:
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QHBoxLayout> #include <QPushButton> #include <QScrollArea>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);QScrollArea * scrollArea = new QScrollArea(this);QWidget * pWgt = new QWidget;QHBoxLayout *pLayout = new QHBoxLayout();//網(wǎng)格布局for(int i = 0; i < 100; i++){QPushButton *pBtn = new QPushButton();pBtn->setText(QString("按鈕%1").arg(i));pBtn->setMinimumSize(QSize(60,30)); //width heightpLayout->addWidget(pBtn);//把按鈕添加到布局控件中}pWgt->setLayout(pLayout);//這一句setWidget必須放在pWgt里面的內(nèi)容都準(zhǔn)備完畢之后,否則顯示有問題scrollArea->setWidget(pWgt);setCentralWidget(scrollArea); }MainWindow::~MainWindow() {delete ui; }?
總結(jié)
以上是生活随笔為你收集整理的QT的自动滚动区QScrollArea的用法,图文详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 泊松分布的期望和方差推导
- 下一篇: s3c2440移植MQTT