資源文件:
QMainWindow :
在菜單欄中
,文件下面的下拉框中,不能直接輸入中文,可以先隨便寫個英文名,然后在對應所屬的狀態欄中找到
,將text右側的“save”改為“保存”
,即可
;
這里的“保存”和“打開”可以通過拖動鼠標來改變順序
;
將菜單欄中的按鈕放入工具欄:在ui界面中的Action Editor里面選擇要放入工具欄的action;然后鼠標點住別放,往工具欄中拖,若出現紅色豎杠,就表示此處可以拖入,此時松開鼠標即可完成拖入。
運行起來的程序,工具欄是可以自由拖動停靠的
,要想不可拖動停靠,可以在ui界面的右側的對象中找mainToolBar,在下面的屬性中找QToolBqr,將movable后面的框框里,把對號去掉,就無法移動了
,將allowedAreas
控件中的Dock Widget是浮動窗口;屬性中的floating是浮動與否,windowTitle是浮動窗口的小標題

QMenu (菜單欄)----- 只有一個
toolbar (工具欄)----- 可以有很多個
dockwidget (浮動窗口)--可以有很多個
statusBar(下狀態欄)----- 只有一個
程序中,初始化一個變量的方式有兩種: 在.h的private下面定義一個int number; 可以在.cpp中
這樣初始化.
qt中,通過代碼添加資源文件(.qrc)如圖:
方式一:
這種比較麻煩;
方式二:
可以通過右鍵左側文件夾 -> 添加新文件-> 文件和類"Qt" -> Qt Resource File -> choose -> 指定名稱(英文) -> .qrc 添加到文件 -> 完成 -> 項目所屬的.pro中出現 Resource += ***.qrc
此時左側文件樹中出現
,雙擊resource.qsc是無法打開的, 此時想要編輯,應該鼠標右鍵單擊resource.qrc -> Open With -> 資源編輯器;
打開后, 點擊 "添加" 按鈕 -> 添加前綴 -> 修改前綴(最簡單的前綴就是一個/) -> 點擊 "添加" 按鈕 -> 添加文件 -> 將所用到的圖標資源文件放入一個Image文件夾中, 再復制粘貼到工程所在目錄中 -> 鼠標左鍵拉選所用圖片 -> 選好后,點擊右下方 "打開" 即可完成添加資源文件;
此時的左側文件樹
可以看到資源文件, 同時, 可以在添加前綴那塊在添加個文件前綴, 放別的資源文件進來, 方便后期項目過大時區分資源文件;
同時,將.cpp文件中的資源文件地址更換
ui->actionsave_as->setIcon(QIcon(":/caidanlan/Image/1.jpg"));
此時的程序編譯時, 運行速度會變慢, 是因為編譯器在編譯的時候, 將我們所添加的資源文件, 轉換成了二進制文件, 存入了程序中, 以后打包軟件的時候,也將圖片一起打包了就.
方式三:
添加完資源文件前綴及文件后,在.ui界面的Action Editor中,選擇所要添加資源文件的action
; 然后查看右側的屬性窗口里找icon
點開下拉框后,找到Normal Off/On,然后點擊其中一個
右側的 "..." ,彈出資源文件窗口
;此時選擇一個圖標, 選擇, 點擊OK即可;此時
出現圖標,若想改變圖標大小, 可在.ui界面的右側的對象窗口里 找到並選中mainToolBar
, 然后在右下角的屬性窗口中,找到QToolBar -> iconSize, 在這里可以改變圖標的寬高;iconText是圖標文本內容; 當圖標插入后,Qt默認不顯示文字,可將鼠標懸浮於圖標之上,1s后,可顯示出提示文字;提示文字可在iconText同級下面一行的toolTip后面設置;
QDialog :
模態對話框: 無法對對話框后的文件進行編輯或處理;且有系統提示音;
非模態對話框: 可以對對話框后的文件進行編輯或處理;
PS: 使用QT類主要記 這個類, 都有哪些信號, 和槽函數. Qt中,用宏的時候,記不住宏的名字,也可以用宏編碼
dlg->setAttribute(Qt::WA_DeleteOnClose); //關閉窗口后,自窗口自動被析構.此處的是QObject派生的子類,父類窗口不關閉(析構),子類也不會被析構
//dlg->setAttribute(55); //在文檔助手里,上述宏對應的編號就是55
QMessageBox:
提示對話框:
本節代碼如下:
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QDebug> #include <QPushButton> #include <QLabel> #include <QDialog> //對話框類 #include <QMessageBox> //提示對話框 #include <QColorDialog> //顏色對話框 #include <QFontDialog> //字體對話框 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), number(10) //初始化 方式1 { ui->setupUi(this); //number = 10; //初始化 方式2 //ui->menuEdit->addAction(); connect(ui->actionopen, &QAction::triggered, this, [=]() { // //創建一個對話框 // QDialog dlg(this); //如果沒有(this),意思是dlg是個獨立的頂層窗口,加了(this)意思是,指定了父類是MainWindow(看本代碼第九行) // //顯示模態對話框 .exec() // dlg.exec(); //阻塞 關閉模態對話框后,程序才可以繼續執行 // QString name = QFileDialog::getOpenFileName(this, "打開文件", "D:\\", "Image (*.jpg *.png )"); // qDebug() << name.toUtf8().data(); //qDebug不能直接打印Qstring類型的,需要先轉成QByteArray{toUtf8()},,再轉成char *QByteArray {data()} //QMessageBox::about(this,"about","*******"); //QMessageBox::critical(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel); // | 是為了區分,在Open的時候可能會加參數,比如只讀/只寫, QMessageBox::Ok 和QMessageBox::Cancel 對應的都是數值, 轉換為二進制后, 只占其中一位.將這兩個按位異或的方式放入整數里,占很多的位,通過對應位來判斷所設屬性 //if(QMessageBox::Ok == QMessageBox::critical(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel)) //是個紅色大錯號 //if(QMessageBox::Ok == QMessageBox::information(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel)) //是個藍色感嘆號 //if(QMessageBox::Ok == QMessageBox::warning(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel)) //是個黃色感嘆號, 並設置Cancel為默認按鈕 // if(QMessageBox::Ok == QMessageBox::question(this,"error","系統文件錯誤!!!",QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel)) //是個藍色問號 // { // QDialog dlg(this); // dlg.exec(); // } // QColor color = QColorDialog::getColor(); // qDebug() << color.red() << color.green() << color.blue(); //顏色對話框 bool ok; QFont font = QFontDialog::getFont(&ok, QFont("華文彩雲"), this, "我的字體設置"); if(ok) { qDebug() << font.family() << font.italic() << font.pointSize() << font.bold(); //字體類型 << 傾斜與否 << 高度 << 加粗與否 } }); connect(ui->actionsave, &QAction::triggered, this, [=]() { //創建一個對話框 QDialog *dlg = new QDialog(this); //此時運行,非模態對話框一閃而過,此處new是為了不析構這個dlg,使對話框一直存在,也可以while(1){} //但是弊端是,這個程序運行起來后,有可能會反復點擊一萬次"save"按鈕, 來創建這個窗口, 這就意味着被new了一萬次, 但是一次都沒被析構. 解決辦法是 將QDialog *dlg定義為成員變量.這樣就可以在外部釋放,這樣比較麻煩. //也可以設置對話框屬性 dlg->setAttribute(Qt::WA_DeleteOnClose); //關閉窗口后,自窗口自動被析構.此處的是QObject派生的子類,父類窗口不關閉(析構),子類也不會被析構 //dlg->setAttribute(55); //在文檔助手里,上述宏對應的編號就是55 //顯示非模態對話框 .show() dlg->show(); //非阻塞 }); ui->dockWidget->show(); //浮動窗口 QPushButton* btn = new QPushButton("hello",this); //給下狀態欄的左側添加“hello”按鈕 ui->statusBar->addWidget(btn); //下狀態欄 QLabel* label = new QLabel("world",this); //給下狀態欄“hello”按鈕的左側添加一個label顯示內容為"world" ui->statusBar->addWidget(label); //ui->actionsave_as->setIcon(QIcon("D:\\1.jpg")); //給菜單欄下拉框中的"save as"添加圖標,圖標路徑為:D:/1.jpg //添加完資源文件后, 可用下面這種添加方式 ui->actionsave_as->setIcon(QIcon(":/caidanlan/Image/1.jpg")); } MainWindow::~MainWindow() { delete ui; }
布局:
一般ui界面中,常用的是前三種布局
垂直布局, 水平布局, 網格布局.
水平布局:使所選空間處於水平位置;
eg:在ui界面拖入兩個label和兩個Text Browser
, 選中用戶名和右邊的Text Browser, 點擊ui界面上方的水平布局,此時變為
;
但是不推薦使用,因為很容易水平變為右圖這種
; 順序搞反后,不容易點擊改變;
建議先放入一個widget窗口,再將用戶名和Text Browser放入widget窗口,
,選中widget窗口后,點擊水平布局即可,
,密碼和Text Browser2,同理, 兩個按鈕同理,最上面的label不用管,如圖
,狀態樹的所屬為:
垂直布局: 選中
后, 點垂直布局, 變為:
;
此時拉拽ui界面, 按鈕和框表會隨之改變,要想讓上方的label中的內容居中,可在對應label所屬的屬性框中找到
,將水平的格式調為AlignVCenter,或者同理, 把label放入widget中, 再做一個水平布局;
加彈簧,彈簧也可以設置屬性,sizeType中,Expanding,是默認可伸展的彈簧, Fixed是固定彈簧長度,
按鈕固定大小:在按鈕的屬性框中,找到
,將最大和最小的寬度設置為同一數值, 按鈕大小就不會發生改變,或者兩個按鈕中間加個彈簧;
水平和垂直布局只能改變一行或一列, 效果圖如下

網格布局: 打破用戶名和密碼的布局后,將這四個模塊放入同一個widget,然后選擇網格布局, 此時,
, 將整個主窗口Widget垂直布局,將最大和最小的寬高都設置為192*173,此時:
,用戶名左側邊框太寬,可以在主窗口Widget的屬性中,找到
將layoutLeftMargin 設置為0. Top是頂部間距, Right是右側邊距, Bottom是底部邊距, Spacing是控件直接的默認邊距
控件介紹:
Layouts(布局): 垂直 水平 網格 表格
Spaces(彈簧): 水平 垂直
Buttons(按鈕):
Push Button 普通按鈕 三種信號:點擊clicked ;按下pressed ; 釋放 released; 可以給按鈕設置圖標
Radio Button 單選按鈕 成組使用, ui界面的多個按鈕只可點擊一個.要想分兩組使用, 將一組單選按鈕放入Group Box框中. 比如性別 只有男女, 單選題.
Check Box 復選按鈕 可以有多個選擇, 沒有選擇限制. 比如愛好, 多選題. 信號是stateChanged, 使用lambda表達式時,()中要加參數 int state
connect(ui->checkBox, &QCheckBox::stateChanged, this, [=](int state)
{
QMessageBox::information(this, "checkbox", QString::number(state));
//QString::number(state) 把int型的state轉為字符串
qDebug() << state; //選中復選框就打印2 未選就打印0
});
Item Views 比較高級, 老師不給教
Item Widget:
List Widget 數據一行一行的顯示
ui->listWidget->addItem("hello,world!"); //QListWidgetItem* Item = new QListWidgetItem(QIcon("C:\\Users\\muchai\\Desktop\\1.jpg"),"l",ui->listWidget); //ui->listWidget->addItem(Item); ui->listWidget->addItem(new QListWidgetItem(QIcon("C:\\Users\\muchai\\Desktop\\1.jpg"),"1"));

Table Widget 數據如Excel表顯示, 有行列表格線. 使用時需要指定行數 列數;
//1、指定行數 ui->tableWidget->setRowCount(100); //2、指定列數 ui->tableWidget->setColumnCount(3); //給每列起名字 QStringList list; list << "姓名" << "性別" << "年齡" ; //給每行起名字 QStringList list2; list2 << "人員1" << "人員2" << "人員3"; ui->tableWidget->setHorizontalHeaderLabels(list); ui->tableWidget->setVerticalHeaderLabels(list2);
,框中可以進行編輯。
Group Box(組框):一般會將Radio Button放入組框中。
Scroll Area(滾動區域):很小的窗口,顯示很多的內容
Tool Box:抽屜一樣的盒子,像QQ的分組列表,點開后,里面的好友被彈出,Page里面可以放控件,比如在Page1中放入本例的Group Box1,在Page2中放入本例的Scroll Area
,
Tab Widget:選擇頁面,可以設置Tab按鈕的位置,按鈕文字。
,
Stacked Widget(棧窗口):可以設置多個頁面,通過連接按鈕來切換頁面;連接按鈕時,可在Stacked Widget的屬性欄中的QStackedWidget下的currentIndex的數值來查看窗口序號,同時這個序號也是連接外部按鈕的槽函數的參數(此法的槽函數帶int型的參數,與button的clicked的bool返回值不匹配,一般使用lambda表達式作為槽函數使用,在lambda的{}中寫槽函數返回)。除了用序號連接外部按鈕外,還可以根據Stacked Widget對應的窗口屬性欄中QObject下的objectName來連接。
//connect(ui->btn_music, &QPushButton::clicked, ui->stackedWidget, &QStackedWidget::setCurrentIndex()); //信號與槽返回值類型不匹配,前者為bool 后者為int connect(ui->btn_music, &QPushButton::clicked, this, [=]() { ui->stackedWidget->setCurrentIndex(0); //參數可在ui界面的Stacked Widget的屬性欄中的QStackedWidget下的currentIndex的數值來查看窗口序號 }); connect(ui->btn_tiktok, &QPushButton::clicked, this, [=]() { ui->stackedWidget->setCurrentWidget(ui->video); //video是Stacked Widget對應的窗口屬性欄中QObject下的objectName }); connect(ui->btn_cale, &QPushButton::clicked, this, [=]() { ui->stackedWidget->setCurrentIndex(2); });

Dock Widget(浮動窗口):可以停靠在主窗口邊框,還可以獨立出來的窗口
Combo Box(下拉框):可以通過additem添加字符串,直接加字符串就行,或者圖標加字符串
Font Combo Box(下拉框):字體下拉框
Label(文本圖形框):可以放入圖片(靜態、動態)或文字;在Qt中 Picture不是圖片,Pixmap才是圖片!!
//ui->label->setPixmap(QPixmap(":/Image/1.jpg")); // QMovie movie(":/Image/yaw.gif"); //這樣不行,因為movie對象創建在構造函數里面,movie對象創建出來后,構造函數里面的對象就被析構了,movie在播放的時候就已經被析構掉了,播放不出來畫面. // ui->label->setMovie(&movie); // movie.start(); QMovie* movie = new QMovie(":/Image/yaw.gif"); ui->label->setMovie(movie); movie->start();

自定義控件: (封裝SpinBox和水平進度條)
Spin Box的默認大小是0-99; 可通過 setRang(0,10000) 來設置Spin Box的大小; 
本節就是將這兩個控件(Spin Box & 滑動條)封裝成一個控件(widget窗口), 方便后期重復使用;
步驟:
1. 先給項目中新建一個類
選中項目的名字, 鼠標右鍵 -> 添加新文件; 此時可以添加一個C++-> C++ Class, 但是C++ Class不帶ui界面, 需要用代碼來創建控件和編輯其屬性;故此處用Qt -> Qt設計師界面類 -> Widget(空白界面,所有類的父類) -> 在<類名:>后面的LineEdit中, 給封裝的類起個響亮的名字(SmallWidget), 頭文件、源文件、界面文件自動修改 -> 完成;
2. 在smallwiddget.ui 中, 將Spin Box 和 水平滑動條放入, 將整個ui界面水平布局, 再將ui界面的窗口拖動到最小;
3. 此時在widget.ui中, 想用封裝的自定義控件, 先在widget.ui中放入一個Widget控件(窗口), 鼠標右鍵單擊剛放入的Widget窗口, 鼠標左鍵選擇 "提升為..."; 在彈出的提升的窗口部件中,基類名稱不用管, 在提升的類的名稱中寫入剛才創建的類的類名(SmallWidget), 寫的時候注意大小寫 ! 頭文件不用管, 選中全局包含(在項目中的任何一個窗口都可以使用此控件) , 點擊 "添加"按鈕. 添加完成后, 提升的類會上升到上面的窗口, 此時點擊對話框底部的"提升"按鈕, 回到widget.ui界面, 此時可以看到ui界面的右側屬性欄中, widget的類名稱已改變成SmallWidget, 而不再是QWidget. 此時再拉入一個widget_2,右鍵單擊 -> 左鍵 "提升為" -> SmallWidget (全局包含的意義:可不限制窗口的將一個QWidget類提升為SmallWidget類)
此時的smallwidget.ui:

此時的widget.ui:
運行界面:

4. 因為把SmallWidget封裝成了一個類, 在SmallWidget類中維護這兩個控件要在smallwidget.cpp中的構造函數中編寫代碼, 進行Spin Box於滑動模塊的對應的信號槽連接,使Spin Box增大,滑塊隨之移動, 滑塊移動, Spin Box隨之改變;
void (QSpinBox::*sigValeChange)(int) = &QSpinBox::valueChanged; //Qt5中不能直接將信號直接寫入connect(因為valuechanged是個重載信號),需要定義一個指針; connect(ui->spinBox, sigValeChange, ui->horizontalSlider, &QSlider::setValue); //&QSlider里面沒有對應的槽函數, 它的父類QAbstractSlider里面有setValue connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);
5. 提供接口函數, 在smallwidget.h的public中,定義接口函數
int getValue(); //獲取值
void SetValue(int value); //設置值
6. 在smallwidget.cpp中實現
void SmallWidget::SetValue(int value)
{
if(value > 0 && value < 100) { ui->spinBox->setValue(value); } } int SmallWidget::getValue() { return ui->spinBox->value(); }
Qt樣式表
在思想上很大程度來自於HTML的層疊式樣式表(CSS), 通過調用 QWidget::setStyleSheet()或QApplication::setStyleSheet(),可為一個獨立的子部件, 窗口, 甚至整個應用程序指定一個樣式表; Qt樣式表與CSS的語法幾乎完全相同.
1. 語法基礎: selector { attribute: value }
eg:(.cpp構造函數中) ui -> label -> setStyleSheet ("QLabel { color: red} "); //為一個獨立的子部件指定一個樣式表
(.cpp構造函數中) this -> setStyleSheet ("QLabel { color: red} "); //為一整個窗口指定一個樣式表(本例中,所有的label都是紅色)
(main.cpp中) a.setStyleSheet ("QLabel { color: red} "); //為整個應用程序指定一個樣式表
當為整個應用程序指定一個樣式表后,可對其中的一個或多個窗口或子部件進行屬性修改; 為窗口指定樣式表后, 也可修改其中的子部件屬性;
選擇器通常為一個類名 (eg: QComboBox), 屬性(attribute)是一個樣式表屬性的名字, 值(value)是賦給該屬性的值;
為方便使用, 可使用以下簡化形式的樣式表:
selector1, selector2, ... ... , selectorM
{
attribute1: value1;
attribute2: value2;
...
attributeN: valueN;
}
這種簡化形式可以同時為與M個選擇器相匹配的部件設置N種屬性
QCheckBox, QComboBox, QSpinBox
{
color: red;
background-color: white;
font: bold;
}
這個規則設置了所有的QCheckBox, QComboBox和QSpinBox的前景色、背景色和字體
2. 方箱模型: 樣式表中, 每個部件都可看成是一個由四個同心的矩形組成的箱體(方框套方框);
空白(margin): 空白區域位於邊框外, 且總是透明
邊框(border): 為部件提供了四周的框架, 其border-style屬性可以設置為一些內置的框架風格,如inset, outset, solid, ridge;
填充(padding):填充在邊框和內容區域之間, 提供了空白間隔.
內容(content): 對於一個平面部件, 例如一個空白、邊框和填充都是0像素的部件而言,這四個矩形完全重合;
3. 前景和背景
前景用於繪制上面的文本, 可以通過color: 屬性指定, 背景色用於繪制部件的填充矩形, 可以通過 background-color: 屬性指定;
背景圖片使用background-image 屬性定義,用於繪制由background-origin指定的矩形區域(空白, 邊框, 填充, 內容), 對齊和平鋪方式可以通過background-position和background-repeat屬性指定;
4. 可伸縮樣式:
默認情況下, 通過background-image指定的背景圖片會自動重復平鋪,以覆蓋部件的整個填充矩形,若我們想創建能夠隨着部件大小自動縮放,而不是平鋪的背景,我們需要設置"邊框圖片". 通過border-image: 指定屬性;
QPushButton{
border-width: 4px;
border-image: url(button.png); /*4 4 4 4 stretch stretch*/ } //注釋里的是往里裁剪圖片的屬性, 設的越大,裁的越多;
5. 控制大小:min-width, min-height (不常用,因為可以直接在ui界面屬性欄中控制)
6. 偽狀態;
ui -> pushButton -> setStyleSheet("QPushButton
{"
"border: 2px outset green;" //按鈕邊框為綠
"}");
偽狀態列表:
:checked button部件被選中
:disabled 部件被禁用
:enable 部件被啟用
:fouces 部件獲得焦點
:hover 鼠標位於部件上
:indeterminate checkbox或radiobutton被部分選中
:off 部件可以切換, 且處於off狀態
:on 部件可以切換, 且處於on狀態
:pressed 部件被鼠標按下
:unchecked button部件未被選中
ui -> pushButton -> setStyleSheet("QPushButton
{"
"border-image:url(:/1.jpg);" //按鈕設置圖標
"}");
ui -> pushButton -> setStyleSheet("QPushButton:hover
{"
"border-image:url(:/1.jpg);" //鼠標位於按鈕上,按鈕圖標亮出
"}");
