控件概述
實現圖形化界面的程序.
Qt中已經給我們提供了很多的“控件"
就需要學習和了解這些控件,學會如何使用這些控件
編程講究的是“站在巨人的肩膀上”,而不是“從頭發明輪子"
一個圖形化界面上的內容,不需要咱們全都從零去實現.Qt中已經提供了很多內置的控件了(按鈕,文本框,單選按鈕,復選按鈕,下拉框.) 咱們拿過來就能直接使用.
QWidget核?屬性
在Qt中,使?QWidget類表?"控件"。像按鈕,視圖,輸?框,滾動條等具體的控件類,都是繼承?QWidget.
可以說,QWidget中就包含了Qt整個控件體系中,通?的部分.
在QtDesigner中,隨便拖?個控件過來,選中該控件,即可在右下?看到QWidget中的屬性
這些屬性既可以通過QtDesigner會直接修改,也可以通過代碼的?式修改.
這些屬性的具體含義,在Qt Assistant中均有詳細介紹.
在Qt Assistant中搜索QWidget,即可找到對應的?檔說明。(或者在Qt Creator代碼中,選中QWidget,按F1也可).
核?屬性概覽
屬性 | 作? |
---|---|
enabled | 設置控件是否可使?. true 表?可?, false 表?禁?. |
geometry | 位置和尺?.包含x,y,width,height四個部分. 其中坐標是以?元素為參考進?設置的. |
windowTitle | 設置widget標題 |
windowIcon | 設置widget圖標 |
windowOpacity | 設置widget透明度 |
cursor | ?標懸停時顯?的圖標形狀. 是普通箭頭,還是沙漏,還是?字等形狀. 在Qt Designer界?中可以清楚看到可選項. |
font | 字體相關屬性. 涉及到字體家族,字體??,粗體,斜體,下劃線等等樣式. |
toolTip | ?標懸停在widget上會在狀態欄中顯?的提?信息. |
toolTipDuring | toolTip顯?的持續時間. |
statusTip | Widget狀態發?改變時顯?的提?信息(?如按鈕被按下等). |
whatsThis | ?標懸停并按下alt+F1時,顯?的幫助信息(顯?在?個彈出的窗?中). |
styleSheet | 允許使?CSS來設置widget中的樣式. Qt中?持的樣式?常豐富,對于前端開發?員上?是?常友好的. |
focusPolicy | 該widget如何獲取到焦點. ? Qt::NoFocus:控件不參與焦點管理,即?法通過鍵盤或?標獲取焦點 ? Qt::TabFocus:控件可以通過Tab鍵獲得焦點 ? Qt::ClickFocus:控件可以通過?標點擊獲得焦點 ? Qt::StrongFocus:控件可以通過鍵盤和?標獲得焦點 ? Qt::WheelFocus:控件可以通過?標滾輪獲得焦點(在某些平臺或樣式中可能不可?) |
contextMenuPolicy | 上下?菜單的顯?策略. ? Qt::DefaultContextMenu:默認的上下?菜單策略,??可以通過?標右鍵或鍵盤快捷鍵觸發上下?菜單 ? Qt::NoContextMenu:禁?上下?菜單,即使??點擊?標右鍵也不會顯?菜單 ? Qt::PreventContextMenu:防?控件顯?上下?菜單,即使??點擊?標右鍵也不會顯?菜單 ? Qt::ActionsContextMenu:將上下?菜單替換為控件的“動作”菜單,??可以通過?標右鍵或鍵盤快捷鍵觸發這個菜單 ? Qt::CustomContextMenu:使??定義的上下?菜單,??可以通過?標右鍵或鍵盤快捷鍵觸發這個菜單 |
locale | 設置語?和國家地區. |
acceptDrops | 該部件是否接受拖放操作。 如果設置為true,那么該部件就可以接收來?其他部件的拖放操作。當?個部件被拖放到該部件上時,該部件會接收到相應的拖放事件(如dropEvent)。 如果設置為false,那么該部件將不會接收任何拖放操作。 |
minimumSize | 控件的最?尺?.包含最?寬度和最??度. |
maximumSize | 控件的最?尺?.包含最?寬度和最??度. |
sizePolicy | 尺?策略.設置控件在布局管理器中的縮放?式. |
windowModality | 指定窗?是否具有"模態"?為. |
sizeIncrement | 拖動窗???時的增量單位. |
baseSize | 窗?的基礎??,?來搭配sizeIncrement調整組件尺?是計算組件應該調整到的合適的值. |
palette | 調?板.可以設置widget的顏??格. |
mouseTracking | 是否要跟蹤?標移動事件. 如果設為true,表?需要跟蹤,則?標劃過的時候該widget就能持續收到?標移動事件. 如果設為false,表?不需要跟蹤,則?標劃過的時候,widget不會收到?標移動事件,只能收到?標按下或者釋放的事件. |
tabletTracking | 是否跟蹤觸摸屏的移動事件. 類似于mouseTracking.Qt5.9中引?的新屬性. |
layoutDirection | 布局?向. ? Qt::LeftToRight:?本從左到右排列,也是默認值。 ? Qt::RightToLeft:?本從右到左排列。 ? Qt::GlobalAtomics:部件的布局?向由全局原?性決定(這個翻譯其實有點尷尬.其實就是根據應?程序中的其他widget布局?向確的). |
autoFillBackground | 是否?動填充背景顏?. |
windowFilePath | 能夠把widget和?個本地?件路徑關聯起來. |
accessibleName | 設置widget的可訪問名稱.這個名稱可以被輔助技術(像屏幕閱讀器)獲取到.這個屬性?于實現?障礙程序的場景中(也就是給盲?寫的程序). |
accessibleDescription | 設置widget的詳細描述.作?同accessibleName |
inputMethodHints | 針對輸?框有效,?來提???當前能輸?的合法數據的格式.?如只能輸?數字,只能輸??期等. |
enabled
API | 說明 |
---|---|
isEnabled() | 獲取到控件的可?狀態. |
setEnabled | 設置控件是否可使?. true 表?可?, false 表?禁?. |
- 所謂"禁?"指的是該控件不能接收任何??的輸?事件,并且外觀上往往是灰?的.
- 如果?個widget被禁?,則該widget的?元素也被禁?
代碼?例:使?代碼創建?個禁?狀態的按鈕
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button = new QPushButton(this);button->setText("按鈕");//按鈕處于禁用狀態button->setEnabled(false);
}Widget::~Widget()
{delete ui;
}
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button = new QPushButton(this);button->setText("按鈕");//按鈕處于禁用狀態button->setEnabled(false);connect(button, &QPushButton::clicked, this, &Widget::handle);
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{qDebug() << "handle";
}
加上槽函數,同樣用不了
切換禁用狀態
創建兩個按鈕
轉到槽,分別給兩個按鈕插入clicked()
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{qDebug() << "執行了槽函數";
}void Widget::on_pushButton_2_clicked()
{// 切換第一個按鈕的禁用狀態// 1.先獲取到第一個按鈕當前的狀態bool enable = ui->pushButton->isEnabled();if (enable) {ui->pushButton->setEnabled(false);}else {ui->pushButton->setEnabled(true);}
}
運?程序,可以看到,初始情況下,上?的按鈕是可?狀態.
點擊下?按鈕,即可使上?按鈕被禁?;再次點擊下?按鈕,上?按鈕就會解除禁?.(禁?狀態的按鈕為灰?,且不可點擊).
QObject的 objectName 屬性介紹:
QObject是QWidget的?類.??最主要的屬性就是 objectName .
在?個Qt程序中, objectName 相當于對象的?份標識,彼此之間不能重復.
在使?Qt Designer時,尤其是界?上存在多個widget的時候,可以通過 objectName 獲取到指定的widget對象.
Qt Designer?成的ui?件,本?是xml格式的.qmake會把這個xml?件轉換成C++的.h?件(這個?件?成在build?錄中),構成?個ui_widget類.
每個widget的 objectName 最終就會成為ui_widget類的屬性名字.
最終這個類的實例,就是 Ui::Widget *ui
,因此就可以通過形如 ui->pushButton 或者 ui->pushButton_2 這樣的代碼獲取到界?上的widget對象了.
在Qt Designer中創建按鈕的時候,可以設置按鈕的初始狀態是"可?"還是"禁?".
如果把enabled這?列的對鉤去掉,則按鈕的初始狀態就是"禁?"狀態.
geometry
位置和尺?.其實是四個屬性的統稱:
- x 橫坐標
- y 縱坐標
- width 寬度
- height ?度
但是實際開發中,我們并不會直接使?這?個屬性,?是通過?系列封裝的?法來獲取/修改.
對于Qt的坐標系,不要忘記是?個"左?坐標系".其中坐標系的原點是當前元素的?元素的左上?
API | 說明 |
---|---|
geometry() | 獲取到控件的位置和尺?.返回結果是?個QRect,包含了x,y,width,height.其中x,y是左上?的坐標. |
setGeometry(QRect) setGeometry(int x,int y,int width,int height) | 設置控件的位置和尺?.可以直接設置?個QRect,也可以分四個屬性單獨設置 |
Rect就是矩形
Qt中針對一些幾何上的概念也進行了封裝
QPoint表示一個點 QRect表示一個矩形
屬于是小對象,里面的屬性非常少,占用空間也小.
C++中使用上述對象,通常就會按照值的方式來傳遞參數了
move只是修改位置
setGeometry既可以修改位置,又可以修改尺寸~
代碼?例:控制按鈕的位置
創建一個按鈕target
修改objectName為pushButton_target
修改這些屬性的時候,一定要先確認好你當前選中的是哪個控件
1)在界?中拖五個按鈕.
五個按鈕的objectName分別為 pushButton_target , pushButton_up ,pushButton_down , pushButton_left , pushButton_right
五個按鈕的初始位置和??都隨意
期望通過點擊這幾個按鈕,就能夠修改target按鈕的geometry
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_up_clicked()
{// 獲取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;
}
單位都是像素
void Widget::on_pushButton_up_clicked()
{// 獲取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setY(rect.y() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setY(rect.y() + 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() - 5);ui->pushButton_target->setGeometry(rect);
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;rect.setX(rect.x() + 5);ui->pushButton_target->setGeometry(rect);
}
當前代碼實際執行的效果,是在調整左上角位置.左上角位置改變的同時,高度和寬度也同時發生了改變
如果想要讓這個按鈕能夠平移.(寬度高度不變,整個按鈕的位置都發生改變)
剛才的代碼,修改的是QRect對象的×和y.這樣的修改就會使QRect寬度高度發生改變
如何才能實現“平移”的效果,保持尺寸不變,整個按鈕位置變化?
不再修改QRect,而是通過QRect基于setGeometry第二個版本的函數重新設置位置即可.
void Widget::on_pushButton_up_clicked()
{// 獲取到target本身的geometryQRect rect = ui->pushButton_target->geometry();qDebug() << rect;
// rect.setY(rect.y() - 5);
// ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}void Widget::on_pushButton_down_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
// rect.setY(rect.y() + 5);
// ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}void Widget::on_pushButton_left_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
// rect.setX(rect.x() - 5);
// ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}void Widget::on_pushButton_right_clicked()
{QRect rect = ui->pushButton_target->geometry();qDebug() << rect;
// rect.setX(rect.x() + 5);
// ui->pushButton_target->setGeometry(rect);ui->pushButton_target->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}
代碼?例:?個表?程序
1)往界?上拖拽兩個按鈕和?個Label.
PushButton的objectName為 pushButton_accept 和 pushButton_reject ,label的objectName為 label
控件中?本如下圖所?
void Widget::on_pushButton_accept_clicked()
{ui->label->setText("女神,嘴一個");
}
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 設置隨機種子,使用時間戳作為隨機種子srand(time(0));
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_accept_clicked()
{ui->label->setText("女神,嘴一個");
}void Widget::on_pushButton_reject_clicked()
{// 如果點擊了這個按鈕,就把這個按鈕挪走// 通過生成隨機數的方式來確定按鈕新的位置// 獲取到當前程序窗口的尺寸int width = this->geometry().width();int height = this->geometry().height();// 重新生成按鈕的位置int x = rand() % width;int y = rand() % height;// 移動按鈕的位置ui->pushButton_reject->move(x, y);
}
rand(是c標準庫中的函數
能夠生成一個隨機的整數.這個數字范圍很大~~
上述代碼就類似于之前寫猜數字,要生成一個1-100之間的整數
rand0 % 100 + 1
[0, 99] + 1 => [1, 100]
rand函數使用之前要設置隨機種子~^
C語言中通過time可以獲取到秒級時間戳~~
按鈕提供的信號不止有點擊
一下一上是點擊,
不再使用clicked信號,換成pressed.鼠標按下的時候觸發
void Widget::on_pushButton_reject_pressed()
{// 如果點擊了這個按鈕,就把這個按鈕挪走// 通過生成隨機數的方式來確定按鈕新的位置// 獲取到當前程序窗口的尺寸int width = this->geometry().width();int height = this->geometry().height();// 重新生成按鈕的位置int x = rand() % width;int y = rand() % height;// 移動按鈕的位置ui->pushButton_reject->move(x, y);
}
也可以做到,鼠標不點擊,只要挪到按鈕上,就會讓按鈕移動~~(需要使用到Qt中的事件機制)
window frame
如果widget作為?個窗?(帶有標題欄,最?化,最?化,關閉按鈕),那么在計算尺?和坐標的時候就有兩種算法.包含window frame和不包含window frame.
其中x(),y(),frameGeometry(),pos(),move()都是按照包含window frame的?式來計算的.
其中geometry(),width(),height(),rect(),size()則是按照不包含window frame的?式來計算的.
當然,如果?個不是作為窗?的widget,上述兩類?式得到的結果是?致的
API | 說明 |
---|---|
x() | 獲取橫坐標 計算時包含window frame |
y() | 獲取縱坐標 計算時包含window frame |
pos() | 返回QPoint對象,??包含x(),y(),setX(),setY()等?法. 計算時包含window frame |
frameSize() | 返回QSize對象,??包含width(),height(),setWidth(),setHeight()等?法. 計算時包含window frame |
frameGeometry() | 返回QRect對象.QRect相當于QPoint和QSize的結合體.可以獲取x,y, width,size. 計算時包含window frame對象. |
width() | 獲取寬度 計算時不包含window frame |
height() | 獲取?度 計算時不包含window frame |
size() | 返回QSize對象,??包含width(),height(),setWidth(),setHeight()等?法. 計算時不包含window frame |
rect() | 返回QRect對象.QRect相當于QPoint和QSize的結合體.可以獲取并設置x, y,width,size. 計算時不包含window frame對象. |
geometry() | 返回QRect對象.QRect相當于QPoint和QSize的結合體.可以獲取x,y, width,size. 計算時不包含window frame對象. |
setGeometry() | 直接設置窗?的位置和尺?.可以設置x,y,width,height,或者QRect對象. 計算時不包含window frame對象. |
在Qt中,關于位置尺寸,提供了很多的API. | |
有的API的位置信息是以Widget本體左上角為原點的(不考慮Windowframe) 有的API的位置信息是以windowframe左上角為原點的. | |
geometry() | |
setGeometry()都是不考慮windowframe | |
frameGeometry() | |
setFrameGeometry()考慮windowframe | |
其實這?的API有frameGeometry和geometry兩個就?夠完成所有的需求了. |
代碼?例:感受geometry和frameGeometry的區別
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 直接針對Widget對象來使用geometry和frameGeometry。觀察區別QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}Widget::~Widget()
{delete ui;
}
當前代碼是放到了構造函數中. 此時這個Widget對象正在構造還沒有被加入到windowframe中
因此,此時還看不到windowframe的影響,
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 直接針對Widget對象來使用geometry和frameGeometry。觀察區別
// QRect rect1 = this->geometry();
// QRect rect2 = this->frameGeometry();
// qDebug() << rect1;
// qDebug() << rect2;QPushButton* button = new QPushButton(this);button->setText("按鈕");button->move(100, 100);connect(button, &QPushButton::clicked, this, &Widget::handle);
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << rect1;qDebug() << rect2;
}