文章目錄
- window frame屬性
- window frame的概念
- 1. window frame的影響
- 2. 圖片演示
- 3. 代碼演示
- API接口
- widget.cpp(測試代碼)
- windowTitle屬性
- API接口
- 問題 + 注意點
- widget.cpp(屬性用法)
- windowIcon屬性
- API接口
- 啥是窗口圖標
- 玩法
- 1. 先看代碼 + 效果圖
- 2. icon傳參問題(特別注意)
- qrc機制(重點)
- 絕對路徑與相對路徑
- 啥是qrc機制 + 解決的問題
- 具體操作流程
window frame屬性
window frame的概念
1. window frame的影響
- 如果
widget
作為?個窗? (帶有標題欄, 最?化, 最?化, 關閉按鈕), 那么在計算尺?和坐標的時候就有兩種算法,看是否包含window frame
和 不包含window frame
這兩種類型 - 其中
x(), y(), frameGeometry(), pos(), move()
都是按照包含window frame
的?式來計算的 - 其中
geometry(), width(), height(), rect(), size()
則是按照不包含window frame
的?式來計算的 - 當然, 如果?個不是作為窗?的 widget , 上述兩類?式得到的結果是?致的.
2. 圖片演示
- 可以通過一些特殊的API接口把
window frame
窗口框架(該操作系統自帶的
)給隱藏掉,比如說一些游戲的運行窗口界面的窗口框架就可以隱藏
3. 代碼演示
- 問題一:下面打印出來的兩個坐標不是一樣的嗎?這是怎么回事。咱們在此處是直接針對
widget
對象來觀察區別,而當前代碼是放到了構造函數中,此時這個widget
對象正在構造,還沒有被加入到window frame
中,因此此時還看不到window frame
的影響
- 問題一的解決方案:直接定義該按鈕的槽函數(
轉到槽定義
),點擊按鈕后,再去打印這兩者原點的坐標
API接口
API | 說明 |
---|---|
x() | 獲取橫坐標 |
y() | 獲取縱坐標 |
pos() | 返回 QPoint 對象,里面包含 x(), y(), setX(), setY() 等方法 |
frameSize() | 返回 QSize 對象 |
frameGeometry() | 返回 QRect 對象 上面五種(包括這一種)計算時包含 window frame |
width() | 獲取寬度 |
height() | 獲取高度 |
size() | 返回 QSize 對象,里面包含 width(), height(), setWidth(), setHeight() 等方法 |
rect() | 返回 QRect 對象 |
geometry() | 返回 QRect 對象。QRect 相當于 QPoint 和 QSize 的結合體。可以獲取 x, y, width, height |
setGeometry() | 直接設置窗口的位置和尺寸。可以設置 x, y, width, height, 或者 QRect 對象。 上面六種(包括這一種)計算時不包含 window frame 對象 |
- 認真觀察上?的表格, 可以看到, 其實這?的 API 有
frameGeometry
和geometry
兩個就?夠完成所有的需求了。為什么要提供這么多功能重復的 API 呢? - 這個就涉及到 Qt API 的設計理念了: 盡量符合?的直覺。舉個例子,Qt 的
QVector
的尾插元素操作,有方法:push_back,append,+=
,上述?法的效果都是等價的,即使不翻閱?檔, 單純的憑借直覺就能把代碼寫對。
widget.cpp(測試代碼)
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
// QRect rect1 = this->geometry();
// QRect rect2 = this->frameGeometry();// // 打印這兩的原點坐標 + 寬度與高度
// qDebug() << rect1;
// qDebug() << rect2;
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();// 打印這兩的原點坐標 + 寬度與高度qDebug() << rect1;qDebug() << rect2;
}
windowTitle屬性
API接口
API | 說明 |
---|---|
windowTitle() | 獲取到控件的窗口標題 |
setWindowTitle(const QString& title) | 設置控件的窗口標題,傳參支持隱式類型轉換,直接傳字符串即可 |
問題 + 注意點
- 問題二的原因:當前的
windowTitle(窗口標題)
屬性是從屬于QWidget
的,QWidget
是一個廣泛的概念,而該屬性只能針對頂層窗口這樣的QWidget
才有效 - 注意點:當前不應該給按鈕設置
windowsTitle
,但是實際設置之后,沒有任何效果,也沒有報錯,但此時沒有報錯
它這樣的設定是不科學的,關于這一點,咱們更希望當代碼寫出不科學的代碼的時候,能夠給一些報錯提示
widget.cpp(屬性用法)
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("這是窗口標題");
}
windowIcon屬性
API接口
API | 說明 |
---|---|
windowIcon | 獲取到控件的窗口標題,返回QIcon 對象 |
setWindowIcon(const QIcon& icon) | 設置控件的窗口圖標 |
同windowTitle,上述操作僅針對頂層
widget
有效
啥是窗口圖標
- 先來說一下這個
QIcon
對象,Qt把各種涉及到的相關概念都封裝成了類,而QIcon就表示一個圖標
玩法
1. 先看代碼 + 效果圖
代碼雖然簡單,但牽扯到的東西卻不這么點,
特別注意路徑和圖片文件名別帶中文,別帶中文!!!帶了后,一堆麻煩事,下面的代碼雖然能成功,但有隱患,坑留在了具體操作流程的最后一步
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 設置圖標--要包含頭文件(頭文件就是類名)--文件名別帶中文QIcon icon("C:/Users/dx156/Pictures/微信圖片_20250418202557.jpg");this->setWindowIcon(icon);
}
2. icon傳參問題(特別注意)
- 傳參傳的是本地圖片的路徑,該路徑最好不要帶有中文!!!我上面的中文是文件名,
C:\Users\dx156\桌面\solidworks.png
(傳入此參數,這種寫法帶有中文路徑) - 這里咱們得使用
/
作為路徑之間的分隔符,也就是上面代碼的寫法,不可使用\
反斜杠作為分隔符,因為它會作為轉義字符,比如\r
這兩字符就被視為是一個字符(回車符
)- 因此為了解決這個問題,除了用
/
作為路徑之間的分隔符外,C++11中引入了raw string(原始字符串)
去解決上述問題,即字符串里不包含任何轉義字符(所有的字符都不會轉義) - 當然針對轉義字符還可以使用雙雙反斜杠
\\
- 因此為了解決這個問題,除了用
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 設置圖標--要包含頭文件(頭文件就是類名)QString text = R"(C:\Users\dx156\Pictures\微信圖片_20250418202557.jpg)";QIcon icon(text);this->setWindowIcon(icon);
}
- 這里的
QIcon
對象是在棧上創建,之前推薦使用堆來創建對象,主要是因為要確保當前的控件的生命周期是足夠的,且要通過Qt對象樹來釋放對象,而Qlcon
自身是一個比較小的對象,創建出來之后,就是要設置到某個QWidget
里面,而且Qlcon
對象本身釋放不釋放,不影響圖標最終的顯示,另外lcon也不支持對象樹,無法給他執行父對象
qrc機制(重點)
絕對路徑與相對路徑
- 絕對路徑的問題:上述代碼傳參傳的該圖片的地址是
絕對路徑
,通過絕對路徑的方式引入圖片是不科學的,畢竟你寫的程序最終是要發布到用戶的電腦上的,那你無法確保,你開發機上圖片的路徑和用戶電腦上圖片的路徑完全一致,比如咱們這個電腦是把圖片放到D盤上,那有可能用戶電腦上只有一個C盤沒有D盤咋辦 - 因此相比于使用絕對路徑的方式,使用相對路徑是更好的
- 相對路徑,是以給定目錄為基準,以
.
或者..
的方式開頭 - 假設基準目錄是
D:/
,給定相對路徑:./rose.jpg
→在基準目錄 (D:/
)直接找rose.jpg
,給定的相對路徑是./image/rose.jpg
→ 在基準目錄中,先找到image
目錄,再在里面找到rose.jpg
- 這個
..
就是到上一級路徑中去找,.
就是到當前在哪個各路徑(基準路徑)就從哪個路徑開始找
- 相對路徑,是以給定目錄為基準,以
- 相對路徑的問題:以相對路徑的形式引入圖片,把圖片和可執行程序放在一個相對合適的位置,比絕對路徑這種方式更好一點。不過要把圖片和可執行程序以相對路徑這個文件一起打包發給用戶,但也無法確保這個文件不會被用戶搞丟
啥是qrc機制 + 解決的問題
- qrc 機制就是從根本上解決上述的兩個問題
- 確保你的圖片所在的路徑在目標用戶機器上存在
- 確保你的圖片不會被用戶搞沒了
- 給 Qt 項目引入一個額外的xml 文件(后綴名使用
.qrc
表示)在這個 xml 中把要使用的圖片資源給導入進來,并且在xml中進行記錄。Qt在編譯項目的時候,就會根據qrc
中描述的圖片信息,找到圖片內容,并且提取出圖片的二進制數據,把這些二進制數據轉成C++代碼,最終編譯到exe里。 - qrc 缺點:無法導入太大的資源文件,比如搞幾個 GB這種視頻文件,qrc 無能為力了
具體操作流程
-
在項目中創建一個
qrc
文件,文件名不要帶中文和特殊符號,直接下一步,下一步
-
來到這個界面后,點擊
Add Prefix
把圖片導入到qrc
中
-
先創建一個前綴(
Prefix
),把Prefix
的名字改成/
即可
- 所謂的
前綴
可以理解成虛擬的目錄,這個目錄沒有在你的電腦上真實存在,是Qt 自己抽象出來的。qrc 機制本質上就是把圖片的二進制數據轉成C++代碼(最終就會在代碼中看到很大的char數組,里面就是圖片的二進制數據),那為了方便 Qt 代碼中訪問到這個圖片,Qt 就自己抽象出了 虛擬的目錄 - 下面的文件是要完整操作了整個流程才會生成的,放在這里是為了輔助理解上面的話語。那
qrc
中導入的圖片資源就會被轉成這個qrc_resource_cpp
這個C++代碼,下面的字節內容就是圖片文件(.jpg
)里每個字節的數據,當Qt項目進行編譯的時候,這個cpp文件就被一起編譯到了exe中,當exe程序運行的時候,上述圖片的數據也被加載到內存中(這是qrc機制工作的本質所在)
- 所謂的
-
把你要使用的圖片給導入到資源文件中。這個按鈕在創建
prefix
之前是禁用的,創建好prefix
之后就可以使用了,添加的文件就是添加到prefix
下面的
-
進行上一步之后,會出現如下問題。因為點擊
Add Files
得到的目錄就是當前代碼所在的目錄
-
將你的圖片拷貝到當前項目目錄中即可。鼠標放在
widget.cpp
文件上,右鍵點擊選擇在Explorer中顯示
,將圖片拷貝到此目錄
-
重復第四步。看到下面的這個效果就說明導入成功了
-
創建的前綴叫啥名字,代碼中寫啥名字。當代碼中需要訪問
qrc
中管理的文件時,就需要在路徑上帶有:: + 前綴名+ 文件名
。我這里最終還是遭了殃:文件名也不能是中文的,.jpg前一堆問號
,先把該文件名給改了,然后鼠標右鍵resource.qrc
打開Open in Editor
重新刪除添加文件
#include "widget.h"
#include "ui_widget.h"
#include<QIcon>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QIcon icon(":/image.jpg");this->setWindowIcon(icon);
}Widget::~Widget()
{delete ui;
}