)
0.引言現(xiàn)在開(kāi)始介紹的各種Qt中的控件都是繼承自QWidget所以QWidget的屬性在接下來(lái)的控件中都是可以使用的。也就是剛剛QWidget中涉及到的各種屬性/函數(shù)/使用方法針對(duì)接下來(lái)要介紹的Qt中的各種控件都是有效的下面來(lái)學(xué)習(xí)Qt中提供的各種控件。1.PushButton使用QPushButton表示一個(gè)按鈕QPushButton繼承自QAbstractButton類這個(gè)類是個(gè)抽象類是其它按鈕的父類(抽象類包含了純虛函數(shù)無(wú)法創(chuàng)建出實(shí)例對(duì)象。需要?jiǎng)?chuàng)建子類重寫(xiě)上述的純虛函數(shù)才能夠創(chuàng)建出子類的實(shí)例)。這有個(gè)圖描述了按鈕類的繼承體系QAbstractButton里提供了一些這樣的屬性接下來(lái)通過(guò)代碼感受一下這些屬性的效果先來(lái)給按鈕加一個(gè)圖標(biāo)。先把圖片導(dǎo)入到項(xiàng)目中使用qrc的方式管理(后續(xù)編寫(xiě)代碼如果用到一些圖片等外部資源都會(huì)優(yōu)先考慮qrc除非資源太大)添加好后就可以在代碼中訪問(wèn)到resource.qrc里面的文件了。創(chuàng)建一個(gè)按鈕然后進(jìn)行完善并運(yùn)行還可以把圖標(biāo)調(diào)整大一些接下來(lái)給按鈕添加快捷鍵前面寫(xiě)過(guò)一個(gè)例子通過(guò)4個(gè)按鈕控制target按鈕的移動(dòng)。之前的移動(dòng)是通過(guò)鼠標(biāo)點(diǎn)擊按鈕來(lái)實(shí)現(xiàn)的此處就可以引入快捷鍵通過(guò)快捷鍵來(lái)操作。下面寫(xiě)一下此處的按鈕通過(guò)圖片來(lái)表示此處把圖片導(dǎo)入項(xiàng)目的時(shí)候由于圖片多了不想再繼續(xù)放到項(xiàng)目根目錄下了。就創(chuàng)建了image目錄把圖片放到image目錄中此時(shí)就意味著后續(xù)訪問(wèn)到這些圖片就需要再路徑中帶上image這一級(jí)目錄名字。有了圖片資源后下面編輯ui創(chuàng)建界面(屬性中改好名字)右上邊可以看到Qt程序運(yùn)行過(guò)程中對(duì)象樹(shù)的模樣更直觀的看到對(duì)象樹(shù)結(jié)構(gòu)以及每個(gè)對(duì)象的objectName。界面準(zhǔn)備完畢了下面進(jìn)一步的編寫(xiě)構(gòu)造函數(shù)完成初始化操作下面實(shí)現(xiàn)方向鍵的槽函數(shù)運(yùn)行可以看到基本功能都以及沒(méi)有問(wèn)題了。下面設(shè)置快捷鍵在Widget的構(gòu)造函數(shù)中完成這樣程序一啟動(dòng)快捷鍵就有效它的參數(shù)是QKeySequence對(duì)象。key表示按鍵sequence表示序列說(shuō)明按下的快捷鍵不一定是單個(gè)按鍵也可能是組合鍵運(yùn)行發(fā)現(xiàn)可以達(dá)到基本的要求。通過(guò)按鍵的名字來(lái)設(shè)置雖然簡(jiǎn)單但是容易寫(xiě)錯(cuò)。這里還可以通過(guò)按鍵的枚舉來(lái)設(shè)置按鍵快捷鍵這樣可以確保拼寫(xiě)不會(huì)出錯(cuò)。也可以用這種方式寫(xiě)組合鍵比如若是第一種方式則這樣寫(xiě)再說(shuō)說(shuō)連發(fā)功能現(xiàn)在的程序鍵盤快捷鍵默認(rèn)可以連發(fā)但鼠標(biāo)點(diǎn)擊按鈕不可以我們需要設(shè)置一下autoReapeat(true)此時(shí)就可以了。2.Radio ButtonQRadioButton是單選按鈕可以讓我們?cè)诙鄠€(gè)選項(xiàng)中選擇一個(gè)。它也是繼承自QAbstractButton一些屬性和QRadioButton直接相關(guān)下面通過(guò)代碼來(lái)演示先創(chuàng)建一些按鈕(順便修改objectname來(lái)完成性別選擇)接下來(lái)再來(lái)一個(gè)label用來(lái)顯示用戶的結(jié)果此時(shí)界面創(chuàng)建好了接下來(lái)給三個(gè)按鈕添加槽函數(shù)測(cè)試也發(fā)現(xiàn)上述的選擇過(guò)程有排他的效果選了一個(gè)就會(huì)自動(dòng)取消其它的選中狀態(tài)。前面代碼中看到程序一啟動(dòng)是沒(méi)有選中任何選項(xiàng)的我們也可以讓程序一啟動(dòng)有一個(gè)默認(rèn)的選項(xiàng)此時(shí)就會(huì)有默認(rèn)選項(xiàng)了。比如想禁用其他選項(xiàng)現(xiàn)在雖然無(wú)法選中但點(diǎn)擊事件可以響應(yīng)所以checkable只是能夠讓按鈕不被選中仍然可以響應(yīng)點(diǎn)擊事件所以這樣此時(shí)這樣的按鈕徹底變成了灰色點(diǎn)擊后也沒(méi)有用。前面在轉(zhuǎn)到槽時(shí)看到QAbstractButton里提供了很多信號(hào)那這些信號(hào)都是干什么的呢clicked表示點(diǎn)擊pressed表示按下released表示抬起。通過(guò)代碼感受一下創(chuàng)建了一些按鈕然后設(shè)置不同的槽函數(shù)(1關(guān)聯(lián)clicked(bool) 2關(guān)聯(lián)pressed 3關(guān)聯(lián)released 4關(guān)聯(lián)toggled)下面運(yùn)行程序來(lái)看看其余的都好理解說(shuō)說(shuō)4當(dāng)點(diǎn)擊4時(shí)checked從flase狀態(tài)變?yōu)榱藅rue所以會(huì)觸發(fā)toggled信號(hào)。當(dāng)繼續(xù)點(diǎn)擊4就沒(méi)有反應(yīng)了因?yàn)闆](méi)有涉及到切換當(dāng)再次點(diǎn)1看到1這里的clicked確實(shí)觸發(fā)了但是4的toggled也觸發(fā)了因?yàn)樵谂潘麢C(jī)制下4從true變成了false。接下來(lái)結(jié)合上述來(lái)寫(xiě)一個(gè)復(fù)雜一些的例子基于QRadioButton實(shí)現(xiàn)一個(gè)簡(jiǎn)單的模擬點(diǎn)餐的功能。先設(shè)計(jì)一下界面RadioButton默認(rèn)是排他的一旦界面上需要存在“多組”單旋按鈕的時(shí)候希望組和組之間不要有影響。Qt中引入了QButtonGroup類可以針對(duì)單旋按鈕進(jìn)行分組這樣可以確保排他機(jī)制是按照每個(gè)組來(lái)展開(kāi)的。下面完成一下此時(shí)不同組里面就不存在排他了。3.QCheckBox的使用QCheckBox表示復(fù)選按鈕可以在多個(gè)選項(xiàng)中選中任意多個(gè)選項(xiàng)。這個(gè)按鈕的屬性也是繼承自QAbstractButton主要是checkable和checked。下面來(lái)通過(guò)代碼演示一下先創(chuàng)建一下界面下面來(lái)添加槽函數(shù)4.QLabel顯示類控件就是用來(lái)在界面上顯示一段內(nèi)容的。其中最主要用到的控件就是Label標(biāo)簽這是Label或QLabel類的一些重要的屬性下面通過(guò)代碼來(lái)演示一下先來(lái)演示一下textFormat起到的效果繼續(xù)編寫(xiě)代碼雖然給label設(shè)置了不同的文本格式直接運(yùn)行程序看起來(lái)好像沒(méi)有什么區(qū)別因?yàn)楦晃谋竞蚼arkdown里面1并沒(méi)有包含真正的對(duì)應(yīng)的符號(hào)。下面加些東西讓它看起來(lái)有一些變化這些加的符號(hào)如果加在純文本中只會(huì)被當(dāng)作是純文本的一部分。下面來(lái)用QLabel顯示圖片把圖片資源用qrc機(jī)制管理好然后編輯代碼先把QLabel設(shè)置成和窗口一樣大并且把這個(gè)QLabel左上角設(shè)置到窗口左上角讓整個(gè)QLabel鋪滿整個(gè)窗口。窗口的大小可以在ui文件中選中窗口后看到可以寫(xiě)死也可以不用寫(xiě)死看到圖片并沒(méi)有真的把整個(gè)界面都鋪滿因?yàn)榇翱谑?00*600QLabel也是一樣了圖片就不一定了。我們可以使用scaledContents來(lái)自動(dòng)拉伸現(xiàn)在填充滿了但是我拖動(dòng)窗口又不滿了在上面代碼中我們?cè)跇?gòu)造函數(shù)進(jìn)行了setGeometry尺寸設(shè)置這個(gè)設(shè)置相當(dāng)于是”一次性的“一旦程序運(yùn)行起來(lái)后QLabel的尺寸就固定下來(lái)了。窗口發(fā)生改變此時(shí)QLabel是不會(huì)變化的。那怎樣讓QLabel隨著窗口大小時(shí)時(shí)發(fā)生改變呢這里先提前說(shuō)個(gè)知識(shí)點(diǎn)叫事件。Qt中表示用戶的操作有兩類概念一個(gè)是信號(hào)另一個(gè)是事件。當(dāng)用戶拖拽修改窗口大小的時(shí)候就會(huì)觸發(fā)resize事件(resizeEvent)。像resize這樣的事件是連續(xù)變化的把窗口尺寸從A拖拽到B這個(gè)過(guò)程會(huì)觸發(fā)一系列的resizeEvent。此時(shí)就可以借助resizeEvent來(lái)完成上述的功能可以讓W(xué)idget窗口類重寫(xiě)父類(QWidget)的resizeEvent虛函數(shù)。在鼠標(biāo)拖拽窗口尺寸的過(guò)程中這個(gè)函數(shù)就會(huì)被反復(fù)的調(diào)用執(zhí)行。每次觸發(fā)一個(gè)resizeEvent事件都會(huì)調(diào)用一次對(duì)應(yīng)的虛函數(shù)。由于此處進(jìn)行了重寫(xiě)調(diào)用父類的虛函數(shù)就會(huì)實(shí)際調(diào)用到子類的對(duì)應(yīng)的函數(shù)。下面來(lái)實(shí)現(xiàn)我們可以打印來(lái)看看發(fā)現(xiàn)拖拽的過(guò)程中發(fā)生了一系列的打印。在實(shí)際編程中指定回調(diào)函數(shù)其實(shí)有很多種寫(xiě)法1.設(shè)置函數(shù)指針。2.設(shè)置仿函數(shù)(函數(shù)對(duì)象)。3.設(shè)置lambda。4.通過(guò)重寫(xiě)父類虛函數(shù)(框架種拿著父類的指針調(diào)用這個(gè)函數(shù)如果你創(chuàng)建了子類重寫(xiě)了這個(gè)函數(shù)此時(shí)在多態(tài)機(jī)制下實(shí)際執(zhí)行的就是子類的函數(shù)了)。5.Qt的信號(hào)槽。繼續(xù)來(lái)完善代碼此時(shí)label尺寸始終和窗口大小是一致的。接下來(lái)看QLabel的文本對(duì)齊自動(dòng)換行縮進(jìn)邊距相關(guān)的屬性。先在界面上創(chuàng)建一些label出來(lái)在QtCreator右側(cè)屬性編輯區(qū)能夠看到類之間的繼承關(guān)系。QLabel繼承自QFrameQFrame繼承自QWidget。QFrame中有個(gè)frameShape屬性通過(guò)修改它可以給label加邊框接下來(lái)針對(duì)這些label來(lái)設(shè)置它不同的屬性下面演示一下QLabel伙伴可以把QLabel和一個(gè)像單選框、復(fù)選框這樣的控件綁定為一個(gè)伙伴關(guān)系此時(shí)可以通過(guò)QLabel觸發(fā)單選框或復(fù)選框等選擇操作。下面先ui中編輯然后用代碼把它們關(guān)聯(lián)起來(lái)此時(shí)我按ALTB對(duì)應(yīng)的選項(xiàng)就可以被選中。Qt中QLabel中寫(xiě)的文本是可以指定”快捷鍵此處快捷鍵的規(guī)則功能上要比QPushButton弱很多。是在文本中使用跟上一個(gè)字符來(lái)表示快捷鍵比如A通過(guò)鍵盤上的atla來(lái)觸發(fā)這個(gè)快捷鍵。綁定了伙伴關(guān)系后通過(guò)快捷鍵就可以選中對(duì)應(yīng)的單選按鈕/復(fù)選按鈕。5.QLCDNumberQLCDNumer是一個(gè)專門用來(lái)顯示數(shù)字的控件類似于 老式計(jì)算器 的效果。這是它的一些核心屬性下面通過(guò)代碼來(lái)感受一下我們寫(xiě)一個(gè)倒計(jì)時(shí)使用QLCDNumber顯示一個(gè)初始的數(shù)值比如10每隔1秒鐘數(shù)字就-1一直到0就停止了。打開(kāi)ui文件拖拽LCDNumber接下來(lái)完善代碼此處的關(guān)鍵點(diǎn)是要實(shí)現(xiàn)“每秒鐘-1”這個(gè)效果怎樣去實(shí)現(xiàn)這樣的效果呢它所體現(xiàn)的問(wèn)題是周期性的執(zhí)行某個(gè)邏輯。這種周期性執(zhí)行某個(gè)問(wèn)題我們往往會(huì)封裝成一個(gè)組件供我們使用這類組件我們稱為定時(shí)器。C標(biāo)準(zhǔn)庫(kù)中沒(méi)有定時(shí)器的實(shí)現(xiàn)Boost里面提供了對(duì)應(yīng)的功能。Qt中也封裝了對(duì)應(yīng)的計(jì)時(shí)器它結(jié)合了信號(hào)槽的機(jī)制。Qt中提供了QTimer類通過(guò)這個(gè)類創(chuàng)建出來(lái)的對(duì)象就會(huì)產(chǎn)生一個(gè)timeout這樣的信號(hào)可以通過(guò)start方法來(lái)開(kāi)啟定時(shí)器并且參數(shù)中設(shè)定觸發(fā)timeout信號(hào)的周期。然后結(jié)合connect把這個(gè)timeout信號(hào)綁定到需要的槽函數(shù)中就可以執(zhí)行邏輯修改LCDNumber中的數(shù)字了。下面實(shí)現(xiàn)此時(shí)運(yùn)行程序就可以看到計(jì)時(shí)器正常工作了。此時(shí)可能會(huì)有疑惑這個(gè)代碼不用QTimer能不能達(dá)成類似的效果呢比如構(gòu)造函數(shù)里弄一個(gè)循環(huán)下面來(lái)試一試先創(chuàng)建ui文件接下來(lái)完善代碼以前c語(yǔ)言中用過(guò)Sleep這個(gè)Sleep是Windows的api需要包含“Windows.h”頭文件才能使用的。這個(gè)東西只能在vs中使用qt用mingw gcc windows版本的編輯器無(wú)法使用Windows.h。在c11標(biāo)準(zhǔn)庫(kù)中引入了sleep操作叫做sleep_for我們來(lái)使用我們運(yùn)行后發(fā)現(xiàn)程序一直沒(méi)有出來(lái)等了一會(huì)程序窗口出來(lái)了但是顯示的是0這里是Widget的構(gòu)造函數(shù)需要把Widget構(gòu)造完畢然后才能show執(zhí)行后續(xù)的顯示操作因此達(dá)不到預(yù)期的倒計(jì)時(shí)的效果。那可不可以在構(gòu)造函數(shù)中另外創(chuàng)建一個(gè)線程在新的線程中執(zhí)行上述循環(huán)更新操作我們?cè)囈幌逻\(yùn)行發(fā)現(xiàn)提示我們進(jìn)程終止了。Qt里界面有一個(gè)專門的線程去負(fù)責(zé)維護(hù)更新的(主線程)。對(duì)于GUI來(lái)說(shuō)內(nèi)部包含了很多的隱藏狀態(tài)Qt為了保證修改界面的過(guò)程中線程安全是不會(huì)受到影響的Qt禁止了其它線程直接修改界面形如上面30行就是在修改界面。因此Qt為了確保線程安全直接要求所有的對(duì)界面的修改操作必須在主線程中完成。對(duì)于Qt的槽函數(shù)來(lái)說(shuō)默認(rèn)情況下槽函數(shù)都是由主線程調(diào)用的在槽函數(shù)中修改界面是沒(méi)有任何問(wèn)題的。在main函數(shù)后面有execexec就會(huì)使主線程進(jìn)入“事件循環(huán)”exec就會(huì)一直循環(huán)下去每執(zhí)行一次循環(huán)都會(huì)有一些固定的事情要操作比如執(zhí)行槽函數(shù)。6.QProgressBar它表示一個(gè)進(jìn)度條這里有進(jìn)度條的一些相關(guān)的屬性接下來(lái)通過(guò)代碼感受一下創(chuàng)建一個(gè)進(jìn)度條讓這個(gè)進(jìn)度條的進(jìn)度跟隨事時(shí)間增長(zhǎng)(可以假設(shè)每隔100ms讓進(jìn)度條數(shù)值1)。先來(lái)編輯ui文件然后切回代碼運(yùn)行程序就可以看到進(jìn)度條在增長(zhǎng)了。這有個(gè)細(xì)節(jié)上述代碼中我們把QTimer頭文件放在了widget.h中在前面QLCDNumber中頭文件包含是放在.cpp中的。我們現(xiàn)在放過(guò)來(lái)程序還是可以正常運(yùn)行的此時(shí)可以看到一個(gè)問(wèn)題我們雖然在widget.h中用到了QTimer但是確沒(méi)在.h中包含QTimer頭文件。那為啥這個(gè)代碼編譯不會(huì)出錯(cuò)為啥此處的QTimer就不會(huì)提示‘找不到定義’之類的錯(cuò)誤上述問(wèn)題其實(shí)是通過(guò)Qt內(nèi)部提供的一個(gè)特殊技巧來(lái)實(shí)現(xiàn)的在Qt中有一個(gè)專門的頭文件這個(gè)頭文件中包含了Qt中所有類的“前置聲明”這個(gè)頭文件一般不會(huì)直接接觸到但是包含其它的Qt的頭文件都會(huì)間接的包含到這個(gè)頭文件。因此前面沒(méi)有報(bào)錯(cuò)是由于在WIdget類的前面已經(jīng)提供了QTimer類的聲明的話此時(shí)就可以在Widget中使用QTimer的指針/引用類型的成員。這個(gè)是C中的特殊技巧在Qt中被使用到了。后續(xù)如果真正使用QTimer(包括創(chuàng)建實(shí)例使用里面的成員)仍然需要包含QTimer的頭文件(包含了QTimer的詳細(xì)的類的定義)。上面的代碼中進(jìn)度條是綠色的那能不能改成是一個(gè)紅色的進(jìn)度條。重新創(chuàng)建編輯uiQProgressBar::chunk是個(gè)選擇器就是咱們?cè)O(shè)置的樣式到底要針對(duì)哪個(gè)控件。chunk就是這個(gè)部分就是把背景色改為了紅色。變紅色后發(fā)現(xiàn)數(shù)字跑到左上角了(可能是Qt的bug)。雖然不能放在最初的位置了但是可以自己調(diào)整一下7.QCalendarWidget它表示一個(gè)日歷這是一些相關(guān)的屬性這是它提供的一些信號(hào)下面通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)用一下日歷的使用方式。在ui中編輯我們用日歷里提供的信號(hào)通過(guò)這個(gè)信號(hào)表示選中的內(nèi)容是哪一個(gè)。繼續(xù)完善此時(shí)點(diǎn)擊哪一個(gè)日期label里就會(huì)顯示哪一個(gè)日期。8.QLineEdit下面開(kāi)始介紹一些輸入類的控件和前面顯示類的控件不同顯示類的控件只是負(fù)責(zé)顯示輸入類控件既能顯示又能讓用戶去輸入一些內(nèi)容。使用最廣泛的輸入類控件是QLIneEdit表示單行輸入框可以輸入一段文本不能換行。這是它的一些核心屬性這個(gè)text屬性不僅僅可以通過(guò)代碼來(lái)設(shè)置用戶在輸入框中進(jìn)行編輯也會(huì)影響到text值的變化。這還有一些關(guān)于輸入框的信號(hào)下面通過(guò)代碼來(lái)感受一下讓用戶輸入我們指定的個(gè)人信息然后通過(guò)提交按鈕把上述內(nèi)容給統(tǒng)一獲取到。先來(lái)編輯ui文件下面切回代碼下面測(cè)試一下上述例子中我們使用InputMask屬性來(lái)驗(yàn)證用戶輸入的是否是一個(gè)正確的電話號(hào)碼但是inputMask功能比較有限只能進(jìn)行簡(jiǎn)單的驗(yàn)證。若想進(jìn)行更復(fù)雜的驗(yàn)證就需要使用”正則表達(dá)式“。它是一個(gè)計(jì)算機(jī)中的通用概念和具體的編程語(yǔ)言無(wú)關(guān)。正則表達(dá)式本質(zhì)上就是一個(gè)帶有特殊字符的字符串特殊字符用來(lái)表示另一個(gè)字符串的特征此時(shí)就可以借助正則表達(dá)式來(lái)描述出一些具有一定特點(diǎn)的字符串基于這些特點(diǎn)就可以完成字符串的匹配。這是正則表達(dá)式的語(yǔ)法正則表達(dá)式語(yǔ)法 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ae5bf541(vvs.90)?redirectedfromMSDN這是正則表達(dá)式測(cè)試的在線工具正則表達(dá)式語(yǔ)法測(cè)試工具 - 在線工具 (buyaocha.com)https://regextester.buyaocha.com/用到的時(shí)候查就可以了。接下來(lái)通過(guò)正則表達(dá)式來(lái)對(duì)輸入框輸入手機(jī)號(hào)驗(yàn)證一下先編輯ui此處的規(guī)則是輸入框要檢查輸入的內(nèi)容是否是合法的手機(jī)號(hào)碼如果是則按鈕設(shè)為可用狀態(tài)如果不是則設(shè)為禁用狀態(tài)。下面編輯代碼這是一個(gè)簡(jiǎn)單的驗(yàn)證手機(jī)號(hào)碼的正則表達(dá)式。^表示以xxx開(kāi)頭^1意思就是以1開(kāi)頭\d表示數(shù)字為了在c字符串中使用需要寫(xiě)作\\d{10}表示前面的內(nèi)容重復(fù)出現(xiàn)10次\d數(shù)字要重復(fù)出現(xiàn)10次$表示結(jié)尾。繼續(xù)寫(xiě)現(xiàn)在只是注冊(cè)了一個(gè)驗(yàn)證器具體驗(yàn)證器怎么使用還需要寫(xiě)其它代碼來(lái)完成。驗(yàn)證輸入框的內(nèi)容是否合法只要輸入框的內(nèi)容發(fā)生改變了驗(yàn)證操作就應(yīng)該被執(zhí)行。繼續(xù)寫(xiě)下面驗(yàn)證一下下面再基于LineEdit寫(xiě)一個(gè)例子來(lái)完成驗(yàn)證兩次輸入的密碼是否一致。先來(lái)編輯ui文件下面來(lái)完善代碼然后使用textEdited信號(hào)來(lái)觸發(fā)對(duì)于兩個(gè)輸入框內(nèi)容的判定上述代碼完成了響應(yīng)的要求但是形參我們沒(méi)有用到所以會(huì)有警告。如果想消除警告可以這樣這個(gè)寫(xiě)法是類型轉(zhuǎn)換這個(gè)寫(xiě)法對(duì)于代碼的實(shí)際邏輯是沒(méi)有任何影響的同時(shí)可以”騙過(guò)“編譯器警告就沒(méi)有了。再實(shí)現(xiàn)一個(gè)功能針對(duì)密碼可以切換”顯示密碼“狀態(tài)。先來(lái)編輯ui文件下面來(lái)編輯代碼下面運(yùn)行一下9.QTextEditQTextEdit表示多行輸入框在Qt中表示多行輸入框有QTextEdit和QPlainTextEdit。QPlainTextEdit只能表示純文本QTextEdit不僅能表示純文本還可以表示html和markdown。繼續(xù)說(shuō)QTextEdit這是它所包含的一些核心屬性這有一些相關(guān)的信號(hào)下面通過(guò)代碼來(lái)感受一下我們?cè)谳斎肟蛑休斎雰?nèi)容然后顯示到label上面去。先編輯一下ui文件下面來(lái)寫(xiě)代碼(轉(zhuǎn)textChanged信號(hào))下面再寫(xiě)例子顯示QTextEdit這幾個(gè)信號(hào)(ui文件中放一個(gè)輸入框)。下面演示10.QComboBox它表示下拉框這是它的一些核心屬性這是一些核心方法還有一些信號(hào)下面通過(guò)代碼來(lái)感受一下模擬一下麥當(dāng)勞點(diǎn)餐。先編輯一下ui文件下面編輯代碼此時(shí)就有條目了。現(xiàn)在編輯一下提交按鈕以上就是下拉框基本的使用方式。上面用代碼的方式編輯的下拉框中的內(nèi)容也可以使用圖形化的方式來(lái)進(jìn)行編輯再寫(xiě)一個(gè)例子下拉框里的內(nèi)容很多時(shí)候不是代碼中寫(xiě)死的而是通過(guò)文件/網(wǎng)絡(luò)加載數(shù)據(jù)得到的。下面演示一下通過(guò)文件加載先編輯一下ui文件然后選中從文件中加載老婆的信息。創(chuàng)建一個(gè)文件并填好一些信息繼續(xù)編輯代碼此時(shí)就有了一個(gè)動(dòng)態(tài)改變的效果。11.QSpinBox它表示微調(diào)框大概是這樣的輸入框輸入框可以輸入整數(shù)或小數(shù)右邊有按鈕可以通過(guò)按鈕對(duì)里面的數(shù)值進(jìn)行微調(diào)。這是QSpinBox的一些相關(guān)的屬性還有一些相關(guān)的信號(hào)下面通過(guò)代碼來(lái)感受一下還是以點(diǎn)餐為例現(xiàn)在不光可以選則食物還可以通過(guò)微調(diào)框來(lái)選擇具體的數(shù)量。先編輯ui文件下面編寫(xiě)代碼現(xiàn)在細(xì)節(jié)是初始情況下微調(diào)框是0在這個(gè)場(chǎng)景下不合適太多也不科學(xué)我們?cè)俑倪M(jìn)一下12.QDateTimeEdit這些控件是基于微調(diào)框弄出來(lái)的輸入時(shí)間或日期的控件使用QDateEdit作為日期微調(diào)框使用QTimeEdit作為時(shí)間的微調(diào)框使用QDateTime作為時(shí)間日期的微調(diào)框。這幾個(gè)控件用法非常相似下面以QDateTimeEdit為例進(jìn)行介紹。這是關(guān)于QDateTimeEdit的核心屬性最后一個(gè)是使用的時(shí)間規(guī)范。這有一些核心信號(hào)下面通過(guò)代碼感受一下寫(xiě)一個(gè)時(shí)間計(jì)算器計(jì)算兩個(gè)時(shí)間中間的間隔是多少天/多少小時(shí)。先來(lái)編輯ui文件下面來(lái)編寫(xiě)代碼上面的代碼其實(shí)還有些小問(wèn)題發(fā)現(xiàn)此時(shí)的結(jié)果是1天07小時(shí)1號(hào)17點(diǎn)到2號(hào)的0點(diǎn)中間是隔了7個(gè)小時(shí)不是1天07小時(shí)。我們計(jì)算天數(shù)用的daysTo函數(shù)文檔中查有兩個(gè)當(dāng)前我們用的是第二個(gè)點(diǎn)進(jìn)去看看描述說(shuō)明計(jì)算的是之間有多少午夜。因此這樣改進(jìn)一下如果當(dāng)前得到的小時(shí)數(shù)不足24由于次數(shù)是整數(shù)除法就會(huì)舍棄掉小數(shù)點(diǎn)后的內(nèi)容。下面再次運(yùn)行一下13.QDial它表示一個(gè)旋鈕這是它的一些基本的核心屬性這是它的相關(guān)信號(hào)下面通過(guò)代碼來(lái)感受一下先編輯一下ui界面我們要完成通過(guò)旋鈕來(lái)控制窗口的不透明度(opacity)。我們先來(lái)一些設(shè)置下面來(lái)編寫(xiě)(用valueChanged信號(hào))那能否借助這個(gè)旋鈕實(shí)現(xiàn)調(diào)整系統(tǒng)聲音的功能呢可以但是沒(méi)那么容易。調(diào)整系統(tǒng)聲音是Windows系統(tǒng)的apiQt沒(méi)有封裝這個(gè)api此時(shí)就非常麻煩(系統(tǒng)原生的api使用起來(lái)也很麻煩)。此時(shí)就需要通過(guò)vs寫(xiě)一個(gè)動(dòng)態(tài)庫(kù)把系統(tǒng)的原生api封裝一下再讓Qt的程序來(lái)調(diào)用動(dòng)態(tài)庫(kù)。14.QSlider這個(gè)控件表示滑動(dòng)條QSlider和QDial都是繼承自QAbstractSlider因此用法上基本相同。這是它的相關(guān)屬性這是它的核心信號(hào)下面通過(guò)代碼演示一下我們?cè)诖翱谏戏艃蓚€(gè)滑動(dòng)條一個(gè)是水平方向一個(gè)垂直。滑動(dòng)這兩個(gè)滑動(dòng)條就可以調(diào)整窗口的大小。先編輯一下ui文件(往右變大往下變大)下面編寫(xiě)代碼接下來(lái)給兩個(gè)滑動(dòng)條設(shè)置槽函數(shù)接下來(lái)再來(lái)寫(xiě)一個(gè)例子寫(xiě)一個(gè)自定義快捷鍵通過(guò)快捷鍵來(lái)操作滑動(dòng)條。滑動(dòng)條本身可以通過(guò)方向鍵和pageUp和pageDown操作但是咱們也可以自定義。下面編輯ui文件下面編寫(xiě)代碼此時(shí)就可以用我們的快捷鍵來(lái)增加和減小數(shù)值了。15.多元素控件介紹多元素意思是控價(jià)里面包含了很多的元素元素可能指的是字符串也可能是更加復(fù)雜的字符串等。這有一些具體的多元素控件前兩個(gè)表示列表這樣的結(jié)構(gòu)中間兩個(gè)表示表格這樣的結(jié)構(gòu)后面兩個(gè)表示樹(shù)形結(jié)構(gòu)。那上面xxWidget和xxView是什么區(qū)別呢概括來(lái)說(shuō)xxView是更底層的實(shí)現(xiàn)xxWidget是基于xxView封裝而來(lái)的。這樣理解16.QListWidget它表示一個(gè)能夠縱向顯示的列表這是它所涉及到的一些屬性這是它的一些核心方法說(shuō)說(shuō)第一個(gè)列表中的每個(gè)元素/每一項(xiàng)就稱為是一個(gè)item更具體的說(shuō)通過(guò)QListWidgetItem類表示的。再說(shuō)說(shuō)第五個(gè)此處的row參數(shù)就表示插入完畢之后新的元素在第幾行把新元素插入到第幾行之前。這還涉及到一些關(guān)鍵的信號(hào)下面通過(guò)代碼來(lái)感受一下可以輸入框輸入內(nèi)容新增進(jìn)去也可以選中條目刪除。先編輯一下ui文件下面編寫(xiě)代碼先給列表添加一些初始元素。這是另一種添加方式也可以通過(guò)圖形化的方式來(lái)添加選中l(wèi)istWidget右鍵點(diǎn)編輯項(xiàng)目如果這里初始內(nèi)容是固定的此時(shí)通過(guò)哪種方式來(lái)初始化都可以如果這里的內(nèi)容是不固定的要通過(guò)讀取文件/讀取網(wǎng)絡(luò)來(lái)構(gòu)造數(shù)據(jù)就需要通過(guò)代碼的方式來(lái)添加了。切回代碼方式繼續(xù)此時(shí)這樣一個(gè)功能就完成了。還可以再加一些功能17.QTableWidget它表示一個(gè)表格控件一個(gè)表格中包含若干行每一行又包含若干列。這是一些相關(guān)的核心方法這是一些核心信號(hào)表示每一個(gè)單元格可以用QTableWidgetItem這是它的一些方法下面通過(guò)代碼來(lái)感受一下先編輯ui文件下面編寫(xiě)代碼圖像化界面初始化運(yùn)行先看看如果當(dāng)前表格中的數(shù)據(jù)是固定的完全就可以通過(guò)圖形化的方式來(lái)進(jìn)行編輯但實(shí)際開(kāi)發(fā)中很多時(shí)候數(shù)據(jù)是從文件/網(wǎng)絡(luò)中來(lái)的此時(shí)通過(guò)圖形化編輯就不合適了。下面切回代碼繼續(xù)此時(shí)已經(jīng)有了數(shù)據(jù)。下面完善一下按鈕18.QTreeWidget它表示一個(gè)樹(shù)形控件里面的每個(gè)元素都是一個(gè)QTreeWidgetItem每個(gè)QTreeWidgetItem可以包含多個(gè)文本和圖標(biāo), 每個(gè)文本/圖標(biāo)為一個(gè)列。這是它所提供的相關(guān)的方法QTreeWidget控件雖然是樹(shù)形結(jié)構(gòu)但是這個(gè)樹(shù)形結(jié)構(gòu)沒(méi)有體現(xiàn)出根節(jié)點(diǎn)它是從根結(jié)點(diǎn)的下一層子節(jié)點(diǎn)開(kāi)始計(jì)算的這里的樹(shù)畫(huà)橘色框那里表示的是頂層結(jié)點(diǎn)。針對(duì)頂層結(jié)點(diǎn)來(lái)說(shuō)這里也是一個(gè)類似于“List”這樣的結(jié)構(gòu)。這是關(guān)于QTreeWidgetItem核心屬性這是QTreeWidgetItem的核心方法通過(guò)上述知道頂層結(jié)點(diǎn)的相關(guān)操作都是在QTreeWidget這個(gè)類上面的更往后的子節(jié)點(diǎn)都是借助QTreeWidgetItem提供的方法來(lái)操作的。下面通過(guò)代碼感受一下先編輯一下ui界面可以通過(guò)圖形化界面初始化數(shù)據(jù)最上面的1相當(dāng)于樹(shù)根結(jié)點(diǎn)這就是通過(guò)界面的方式來(lái)獲取。下面通過(guò)代碼重新來(lái)操作此時(shí)添加好了頂層結(jié)點(diǎn)。繼續(xù)完善初始化好了后下面實(shí)現(xiàn)一下按鈕的相關(guān)功能上述的幾個(gè)控件相關(guān)的操作數(shù)據(jù)都是在內(nèi)存中保存的無(wú)論界面上做任何操作重新運(yùn)行程序之前的數(shù)據(jù)就都沒(méi)有了。如果要想讓數(shù)據(jù)能夠重新啟動(dòng)也不丟失就需要編寫(xiě)更多的代碼把內(nèi)存存儲(chǔ)的數(shù)據(jù)獲取到寫(xiě)入到文件中并且在下次運(yùn)行的時(shí)候從文件加載數(shù)據(jù)。19.QGroupBox接下來(lái)介紹的控件是容器類控件容器類控件指的是控件里面可以容納其它的一些控件。多元素控件包含的內(nèi)容是一個(gè)一個(gè)的自定義好的“item”對(duì)象。容器類控件包含的內(nèi)容是前面已經(jīng)學(xué)過(guò)的各種控件比如QPushButton、QLineEdit、QLabel等。容器類控件這里主要介紹兩個(gè)一個(gè)是QGroupBox表示分組框還有一個(gè)是QTableWidget表示標(biāo)簽頁(yè)。先來(lái)介紹QGroupBox它大概是這個(gè)樣子可以把其它的各種控件放到GroupBox種這些內(nèi)部的控件的父元素就不是this了而是這個(gè)GroupBox。它存在的意義是為了讓界面看起來(lái)更好看一些。當(dāng)一個(gè)界面比較復(fù)雜的時(shí)候包含了很多控件的時(shí)候分組框就可以把具有關(guān)聯(lián)關(guān)系的控件組織到一起。這是它的核心屬性下面通過(guò)代碼演示一下寫(xiě)一下麥當(dāng)勞點(diǎn)餐先編輯一下ui下面運(yùn)行一下可以看到通過(guò)分組框把這里的控件進(jìn)行了分組可以讓界面看起來(lái)更加清晰有條理。再看看屬性看到勾選后只剩上面一根線了。20.QTableWidget它可以起到一個(gè)帶有標(biāo)簽頁(yè)的效果然后可以在標(biāo)簽頁(yè)里放一些其它的widget。先通過(guò)代碼看一下標(biāo)簽頁(yè)大概是什么樣子可以看到有標(biāo)簽頁(yè)的效果每一個(gè)標(biāo)簽頁(yè)里面都是可以放一些具體的控件的。比如可以放不同的label。如果想有更多的標(biāo)簽頁(yè)或刪除可以這樣現(xiàn)在看看它所提供的屬性這還有一些核心信號(hào)下面通過(guò)代碼感受一下創(chuàng)建一個(gè)程序帶有一個(gè)TableWidget作為標(biāo)簽頁(yè)。提供兩個(gè)按鈕分別創(chuàng)建新的標(biāo)簽頁(yè)關(guān)閉當(dāng)前選中的標(biāo)簽頁(yè)。當(dāng)切換標(biāo)簽頁(yè)的時(shí)候也能感知到變化。先來(lái)編輯ui文件下面編寫(xiě)下面完善按鈕再完善感知到標(biāo)簽頁(yè)切換操作21.QVBoxLayout下面介紹一下Qt中的布局管理器之前把控件放到界面上都是靠“手動(dòng)”的方式來(lái)布局的。但是這種手動(dòng)調(diào)整的方式是不科學(xué)的1.手動(dòng)布局的方式非常復(fù)雜而且不精確。2.無(wú)法對(duì)窗口大小進(jìn)行自適應(yīng)。因此Qt引入了很多布局管理器垂直布局水平布局網(wǎng)格布局表單布局。下面介紹一下垂直布局Qt中使用QVBoxLayout表示垂直的布局管理器。這有一些核心屬性下面通過(guò)代碼感受一下但是每個(gè)widget中只能設(shè)置一個(gè)布局管理器往往可能不夠下面看看如何在widget中弄出多個(gè)布局管理器出來(lái)。先編輯ui文件看到存在兩組Layout每個(gè)Layout包含了多個(gè)按鈕。但此時(shí)調(diào)整窗口大小看到里面的內(nèi)容并不會(huì)像前面那樣隨之發(fā)生變化。如果在代碼中創(chuàng)建layout其實(shí)是只創(chuàng)建了一個(gè)layout。如果在QtDesigner中創(chuàng)建layout先創(chuàng)建了一個(gè)Widget然后再這個(gè)新的Widget中添加了一個(gè)layout。剛才是先拖了layout過(guò)去然后再往layout中托其它控件也可以先托其它控件后給這些控件套上layout這個(gè)按鈕表示把選中的旋若干控件外頭套上一個(gè)垂直布局的layout。22.QHBoxLayout這個(gè)表示水平布局管理器這是它的相關(guān)屬性下面通過(guò)代碼演示一下現(xiàn)在界面上就把這三個(gè)按鈕水平方向排列放到布局管理器中了。布局管理器之間也能進(jìn)行嵌套。我們用一個(gè)垂直布局管理器把兩個(gè)按鈕添加進(jìn)去然后下面弄一個(gè)水平的布局管理器把水平布局管理器添加到垂直布局管理器中再往水平布局管理器里面添加兩個(gè)按鈕。下面實(shí)現(xiàn)23.QGridLayout前面使用水平布局垂直布局可以起到一種二維化布局的方式但是全依賴這個(gè)東西寫(xiě)代碼會(huì)比較的麻煩。于是這里說(shuō)說(shuō)網(wǎng)格布局可以更方便的實(shí)現(xiàn)M*N這樣的一個(gè)效果。這是它的一些屬性下面看看網(wǎng)格布局最基本的使用情況這樣完成了最基本的網(wǎng)格布局。這里是排列成了2*2的效果也可以修改坐標(biāo)起到更加靈活的布局效果這個(gè)寫(xiě)法就相當(dāng)于水平布局了此時(shí)這里的行數(shù)只要是一樣的即可不一定非是0。下面再改變一下代碼這個(gè)寫(xiě)法相當(dāng)于垂直布局了。再比如這種寫(xiě)法是每個(gè)按鈕獨(dú)占一行或一列。若把上述的3,3改為100,100運(yùn)行后發(fā)現(xiàn)是一樣的。說(shuō)明即使設(shè)置成100也不會(huì)在中間搞出很大的空白空間。此處的行數(shù)和列數(shù)只是用來(lái)決定空間之間的相對(duì)位置。接下來(lái)介紹一下布局管理器中拉伸系數(shù)的問(wèn)題我們剛才創(chuàng)建的布局管理器這里的控件尺寸都是均等的。當(dāng)我們需要?jiǎng)?chuàng)建出尺寸不同的控件的時(shí)候就可以通過(guò)拉伸系數(shù)來(lái)設(shè)置。拉伸系數(shù)就相當(dāng)于設(shè)置控件之間尺寸的比列。下面結(jié)合代碼來(lái)演示一下此時(shí)按鈕按照2行3列的方式排列好了。上述按鈕看上去寬度都是一樣的接下來(lái)設(shè)置拉伸系數(shù)這個(gè)拉伸系數(shù)中有個(gè)特殊的取值0如果拉伸系數(shù)設(shè)為0意思是不參與拉伸此時(shí)按鈕的寬度是固定值。此時(shí)調(diào)整窗口大小可以看到第一列的窗口尺寸大小并沒(méi)有改變。接下來(lái)重新創(chuàng)建項(xiàng)目看看垂直方向的拉伸該怎么設(shè)置現(xiàn)在把按鈕按照3行2列的方式排列進(jìn)去了。下面設(shè)置拉伸系數(shù)運(yùn)行發(fā)現(xiàn)代碼看上去沒(méi)什么效果。上述代碼直接設(shè)置拉伸系數(shù)發(fā)現(xiàn)是無(wú)效的。這里之所以沒(méi)有拉伸是因?yàn)镾izePolicy起到的影響。這個(gè)是QWidget的屬性它有這些屬性由于按鈕垂直方向默認(rèn)沒(méi)有拉伸開(kāi)(水平方向默認(rèn)是拉伸的)因此垂直方向不會(huì)受到拉伸系數(shù)的影響了。要想讓垂直方向的拉伸系數(shù)生效就需要讓按鈕先能夠拉伸展開(kāi)看到垂直拉伸打開(kāi)后變化非常大比起之前。有了這個(gè)前提現(xiàn)在再設(shè)置拉伸系數(shù)發(fā)現(xiàn)拉伸可以生效了此時(shí)高度尺寸是1:1:2來(lái)展開(kāi)的。24.QFormLayout下面介紹一下Qt中的表單布局它本質(zhì)上屬于網(wǎng)格布局的一種特殊情況。下面結(jié)合代碼來(lái)演示一下還可以添加按鈕進(jìn)去25.QSpacerItem接下來(lái)介紹一下Qt中的Spacer它是搭配布局管理器使用的工具它表示一段空白。因?yàn)椴季止芾砥骼锬J(rèn)情況下控件和控件之間挨著比較緊如果期望控件之間有一個(gè)比較明顯的間隔就可以使用這樣1一個(gè)類。這是它的一些屬性接下來(lái)通過(guò)代碼演示一下使用情況我們想讓水平方向上有兩個(gè)按鈕然后兩個(gè)按鈕不是僅僅挨在一起的而是中間有空白現(xiàn)在是水平方向排列但是按鈕間非常近。下面來(lái)用空白u(yù)i中也是可以添加空白的它們都是SpaceItem。26.總結(jié)上述的每個(gè)控件都是可擴(kuò)展的。每個(gè)控件都是Qt內(nèi)置的一個(gè)類咱們?cè)诖a中都可以基于這個(gè)類繼承出你自定義的子類。在這個(gè)自定義的子類中又可以添加很多的屬性和方法實(shí)現(xiàn)你自己的需求場(chǎng)景還可以在子類中把多個(gè)控件組合到一起。