Qt界面優化

1.QSS

在網頁前端開發領域中,CSS 是一個至關重要的部分,描述了一個網頁的 “樣式”,從而起到對網頁美化的作用。所謂樣式,包括不限于大小、位置、顏色、背景、間距、字體等等。

網頁開發作為 GUI 的典型代表,也對于其他客戶端 GUI 開發產生了影響,Qt 也是其中之一。Qt 仿照 CSS 的模式,引入了 QSS,來對 Qt 中的控件做出樣式上的設定,從而允許程序猿寫出界面更好看的代碼。

同樣受到 HTML 的影響,Qt 還引入了 QML 來描述界面,甚至還可以直接把一個原生的 html 頁面加載到界面上。當然,由于 Qt 本身的設計理念和網頁前端還是存在一定差異的,因此 QSS 中只能支持部分 CSS 屬性,整體來說 QSS 要比 CSS 更簡單一些。

注意:如果通過 QSS 設置的樣式和通過 C++ 代碼設置的樣式沖突,則 QSS 優先級更高。

1.1基本語法

基本的語法結構

選擇器 {屬性名: 屬性值;
}

其中:

  • 選擇器 描述了 “哪個 widget 要應用樣式規則”
  • 屬性 則是一個鍵值對, 屬性名表示要設置哪種樣式, 屬性值表示了設置的樣式的值
QPushButton {color: red;
}

上述代碼的含義表示, 針對界面上所有的 QPushButton , 都把文本顏色設置為紅色

1.2指定控件樣式設置

QWidget 中包含了 setStyleSheet 方法,可以直接設置樣式

范圍是pushButton_1控件及其所有子控件,進一步通過選擇器選擇的是QPushButton控件

將字體顏色設置為紅色

范圍是窗口及其所有子控件,進一步通過選擇器選擇的是QPushButton控件

將字體顏色設置為紅色

我們是只針對這一個按鈕通過 setStyleSheet 方法設置的樣式,此時這個樣式僅針對該按鈕生效。如果創建其他按鈕,其他按鈕不會受到影響。

1.3設置全局樣式

還可以通過 QApplication 的 setStyleSheet 方法設置整個程序的全局樣式.

全局樣式優點

  • 使同一個樣式針對多個控件生效, 代碼更簡潔
  • 所有控件樣式內聚在一起, 便于維護和問題排查

代碼示例:樣式的層疊特性

如果通過全局樣式給某個控件設置了屬性1,通過指定控件樣式給控件設置屬性2,那么這兩個屬性都會產生作用。

對于第一個按鈕來說,同時具備了顏色和字體大小樣式。而第二個按鈕只有顏色樣式,說明針對第一個按鈕,兩種設置方式設置的樣式,疊加起來了。

形如上述這種屬性疊加的效果,我們稱為 “層疊性”。

代碼示例: 樣式的優先級

如果全局樣式,和指定控件樣式沖突,則指定控件樣式優先展示。

運行程序, 觀察效果,可以看到第一個按鈕已經成為綠色了,但是第二個按鈕仍然是紅色。

在 CSS 中也存在類似的優先級規則. 通常來說都是 “局部” 優先級高于 “全局” 優先級,相當于全局樣式先 “奠定基調” , 再通過指定控件樣式來 "特事特辦。

1.4 從文件加載樣式表

上述代碼都是把樣式通過硬編碼的方式設置的,這樣使 QSS 代碼和 C++ 代碼耦合在一起了,如果QSS代碼簡單就無所謂了,一旦QSS代碼復雜,繼續這樣寫,以后的代碼的維護代價非常的高。因此更好的做法是把樣式放到單獨的文件中,然后通過讀取文件的方式來加載樣式。

先創建一個.qss文件,將其導入到qrc中

編輯.qss文件

將.qss文件中的內容加載到代碼中,寫一個用于加載的函數

這個方案僅供參考,在實際開發中還有更方便的方案。

1.5使用 Qt Designer 編輯樣式

QSS 也可以通過 Qt Designer 直接編輯,從而起到實時預覽的效果,同時也能避免 C++ 和 QSS 代碼的耦合。

代碼示例: 使用 Qt Designer 編輯樣式

1.在界面上創建一個按鈕

    2.右鍵按鈕, 選擇 “改變樣式表”

      3.在彈出的樣式表編輯器中,可以直接填寫樣式,填寫完畢,點擊 OK 即可

        4. 此時 Qt Designer 的預覽界面就會實時顯示出樣式的變化

          5. 運行程序,可以看到樣式確實發生了改變

          這種方式設置樣式, 樣式內容會被以 xml 格式記錄到 ui 文件中

          <property 1 name="styleSheet">
          <string notr="true">QPushButton { color: red; }</string>
          </property>
          

          同時在控件的 styleSheet 屬性中也會體現

          當我們發現一個控件的樣式不符合預期的時候,要記得排查這四個地方:

          • 全局樣式
          • 指定控件樣式
          • qss 文件中的樣式
          • ui 文件中的樣式

          1.6?選擇器

          1.6.1 選擇器概況

          QSS 的選擇器支持以下幾種:

          選擇器示例說明
          全局選擇器*選擇所有的 widget
          類型選擇器 (type selector)QPushButton選擇所有的 QPushButton 和 其子類 的控件
          類選擇器 (class selector).QPushButton 選擇所有的QPushButton 的控件,不會選擇子類
          **ID 選擇器 **#pushButton_2選擇 objectName 為pushButton_2 的控件
          子選擇器QDialog>QPushButton選擇 QDialog 的所有子控件中的QPushButton
          后代選擇器QDialog QPushButton選擇 QDialog 的所有后代(子控件, 孫子控件等等)中的 QPushButton
          **并集選擇器 **QPushButton, QLineEdit,
          QComboBox
          選擇 QPushButton, QLineEdit, QComboBox 這三種控件(即接下來的樣式會針對這三種控件都生效)
          例如:可以寫多個類型選擇器、多個ID選擇器
          屬性選擇器QPushButton[flat=“false”]選擇所有 QPushButton 中,flat 屬性為 false 的控件

          上述選擇器也不需要全都掌握,只熟悉最常用的幾個即可(上述加粗的)。

          1.6.2id 選擇器

          1.在界面上創建 3 個按鈕, objectName 為 pushButton , pushButton_2 , pushButton_3

          2.編寫 main.cpp, 設置全局樣式

          • 先通過 QPushButton 設置所有的按鈕為黃色
          • 再通過 #pushButton 和 #pushButton_2 分別設置這兩個按鈕為紅色和綠色

          執行程序, 觀察效果

          當某個控件身上, 通過類型選擇器和 ID 選擇器設置了沖突的樣式時, ID 選擇器樣式優先級更高。同理, 如果是其他的多種選擇器作用同一個控件時出現沖突的樣式, 也會涉及到優先級問題。實踐中我們可以簡單的認為,選擇器描述的范圍越精準, 則優先級越高。一般來說,ID 選擇器優先級是最高的。

          1.6.3并集選擇器

          1.創建按鈕, label, 單行輸入框

            2.編寫 main.cpp, 設置全局樣式

            1.6.4子控件選擇器

            有些控件內部包含了多個 “子控件” ,比如 QComboBox 的下拉后的面板, 比如 QSpinBox 的上下按鈕等,可以通過子控件選擇器 ::,針對上述子控件進行樣式設置。

            哪些控件擁有哪些子控件, 參考文檔 Qt Style Sheets Reference 中 List of Sub-Controls 章節

            代碼示例: 設置下拉框的下拉按鈕樣式

            1.在界面上創建一個下拉框, 并創建幾個選項

              2.創建 resource.qrc , 并導入圖片 down.png

              3.修改 main.cpp, 編寫全局樣式

              • 使用子控件選擇器 QComboBox::down-arrow 選中了 QComboBox 的下拉按鈕.
              • 再通過 image 屬性設置圖片.

                4.執行程序, 觀察效果

                代碼示例: 修改進度條的顏色

                1.在界面上創建一個進度條

                  2.在 Qt Designer 右側的屬性編輯器中, 找到 QWidget 的 styleSheet 屬性

                  編輯如下內容:

                  • 其中的 chunk 是選中進度條中的每個 “塊”,使用 QProgressBar::text 則可以選中文本
                  QProgressBar::chunk {background-1 color: #FF0000;}
                  

                  同時把 QProcessBar 的 alignment 屬性設置為垂直水平居中

                  此處如果不設置 alignment,進度條中的數字會跑到左上角,這個懷疑是 Qt 本身的 bug,暫時只能先使用 alignment 來手動調整下。

                  3.執行程序, 可以看到如下效果,我們就得到了一個紅色的進度條

                  通過上述方式,也可以修改文字的顏色,字體大小等樣式。

                  1.6.5?偽類選擇器(Pseudo-States)

                  偽類選擇器, 是根據控件所處的某個狀態被選擇的. 例如按鈕被按下, 輸入框獲取到焦點, 鼠標移動到某

                  個控件上等.

                  • 當狀態具備時,控件被選中,樣式生效
                  • 當狀態不具備時,控件不被選中,樣式失效

                  使用 : 的方式定義偽類選擇器

                  常用的偽類選擇器

                  偽類選擇器說明
                  :hover鼠標放到控件上
                  :pressed鼠標左鍵按下時
                  :focus獲取輸入焦點時
                  :enabled元素處于可用狀態時
                  :checked被勾選時
                  :read-only元素為只讀狀態時

                  這些狀態可以使用 ! 來取反,比如 :!hover 就是鼠標離開控件時,:!pressed 就是鼠標松開時等等。

                  更多偽類選擇器的詳細情況,參考 Qt Style Sheets Reference 的 Pseudo-States 章節。

                  代碼示例: 設置按鈕的偽類樣式.

                  1.在界面上創建一個按鈕

                    2.編寫 main.cpp, 創建全局樣式

                    2.運行程序, 可以看到, 默認情況下按鈕文字是紅色, 鼠標移動上去是綠色, 鼠標按下按鈕是藍色

                      上述代碼也可以使用事件的方式來實現

                      代碼示例: 使用事件方式實現同樣效果

                      1.創建 MyPushButton 類, 繼承自 QPushButton

                      把生成代碼中的構造函數改成帶參數 QWidget* 版本的構造函數. (否則無法和 Qt Designer 生成的代碼適配

                        mypushbutton.h

                        把生成代碼中的構造函數改成帶參數 QWidget* 版本的構造函數. (否則無法和 Qt Designer 生成的代碼適配)

                        mypushbutton.h

                        #include 1 <QPushButton>
                        class MyPushButton : public QPushButton
                        {
                        public:MyPushButton(QWidget* parent);
                        };
                        

                        mypushbutton.cpp

                        #include "mypushbutton.h"
                        MyPushButton::MyPushButton(QWidget* parent) : QPushButton(parent)
                        {
                        }
                        

                        右鍵按鈕, 選擇 “提升為”

                        填寫提升的類名和頭文件

                        提升完畢后, 在右側對象樹這里, 就可以看到類型的變化

                          2.重寫 MyPushButton 的四個事件處理函數

                          修改 mypushbutton.h

                          class MyPushButton : public QPushButton
                          {
                          public:MyPushButton(QWidget* parent);void mousePressEvent(QMouseEvent* e);void mouseReleaseEvent(QMouseEvent* e);void enterEvent(QEvent* e);void leaveEvent(QEvent* e);
                          };
                          

                          修改 mypushbutton.cpp

                          • 初始化設為紅色
                          • 鼠標進入時設為綠色, 離開是還原紅色.
                          • 鼠標按下時設為藍色, 松開時還原綠色(松開時鼠標還是在按鈕里)
                          1. 在界面上創建按鈕,并提升為 MyPushButton 類型
                          MyPushButton::MyPushButton(QWidget* parent) : QPushButton(parent)
                          {this->setStyleSheet("QPushButton { color: red; }");
                          }
                          void MyPushButton::mousePressEvent(QMouseEvent *e)
                          {this->setStyleSheet("QPushButton { color: blue; }");
                          }
                          void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
                          {this->setStyleSheet("QPushButton { color: green; }");
                          }
                          void MyPushButton::enterEvent(QEvent *e)
                          {this->setStyleSheet("QPushButton { color: green; }");
                          }
                          void MyPushButton::leaveEvent(QEvent *e)
                          {this->setStyleSheet("QPushButton { color: red; }");
                          }
                          

                            運行程序, 可以看到效果和上述案例一致

                            很明顯,實現同樣的功能,偽類選擇器要比事件的方式簡單很多,但是不能就說事件機制就不好. 事件可以完成的功能很多,不僅僅是樣式的改變,還可以包含其他業務邏輯.,這一點是偽類選擇器無法替代的。

                            1.7樣式屬性

                            QSS 中的樣式屬性非常多,不需要都記住,核心原則還是用到了就去查,大部分的屬性和 CSS 是非常相似的,文檔的 Qt Style Sheets Reference 章節詳細介紹了哪些控件可以設置屬性,每個控件都能設置哪些屬性等。

                            在翻閱文檔的時候涉及到一個關鍵術語 “盒模型” (Box Model)

                            一個遵守盒模型的控件, 由上述幾個部分構成

                            • Content 矩形區域: 存放控件內容. 比如包含的文本/圖標等
                            • Border 矩形區域: 控件的邊框
                            • Padding 矩形區域: 內邊距. 邊框和內容之間的距離
                            • Margin 矩形區域: 外邊距. 邊框到控件 geometry 返回的矩形邊界的距離

                            默認情況下, 外邊距, 內邊距, 邊框寬度都是 0

                            可以通過一些 QSS 屬性來設置上述的邊距和邊框的樣式

                            QSS 屬性說明
                            margin設置四個方向的外邊距,復合屬性
                            padding設置四個方向的內邊距,復合屬性
                            border-style設置邊框樣式
                            border-width邊框的粗細
                            border-color邊框的顏色
                            border復合屬性, 相當于 border-style + border-width + border-color

                            代碼示例: 設置邊框和內邊距

                            1.

                            ? ? ? ? ? ? ? ?

                            1.修改 main.cpp, 設置全局樣式

                            • border: 5px solid red 相當于 border-style: solid;border-width: 5px;border-color: red三個屬性的簡寫形式
                            • padding-left: 10px是給左側設置內邊距

                            2.運行程序,可以看到樣式發生了變化

                            代碼示例: 設置外邊距

                            為了方便確定控件位置, 演示外邊距效果, 我們使用代碼創建一個按鈕

                            1.修改 widget.cpp, 創建按鈕, 并設置樣式

                              2.運行程序, 可以看到, 當前按鈕的邊框被外邊距擠的縮小了. 但是獲取到的按鈕的 Geometry 是不變的

                              1.8控件樣式示例

                              1.8.1按鈕

                              代碼示例:自定義按鈕

                              1.界面上創建一個按鈕

                                2.右鍵 -> 改變樣式表,使用 Qt Designer 設置樣式

                                屬性小結

                                屬性說明
                                font-size設置文字大小
                                border-radius設置圓角矩形,數值設置的越大,角就 “越圓”
                                background-color設置背景顏色

                                運行程序,可以看到此時的復選框就變的豐富起來了

                                1.8.2 復選框

                                代碼示例: 自定義復選框

                                1.創建一個 resource.qrc 文件,并導入以下圖片

                                • 使用黑色作為默認形態
                                • 使用藍色作為 hover 形態
                                • 使用紅色作為 pressed 形態

                                  2.創建一個復選框

                                  3.編輯復選框的樣式

                                    QCheckBox {font-size: 20px;
                                    }
                                    QCheckBox::indicator {width: 20px;height: 20px;
                                    }
                                    QCheckBox::indicator:unchecked {image: url(:/checkbox-unchecked.png);
                                    }
                                    QCheckBox::indicator:unchecked:hover {image: url(:/checkbox-unchecked_hover.png);
                                    }
                                    QCheckBox::indicator:unchecked:pressed {image: url(:/checkbox-unchecked_pressed.png);
                                    }
                                    QCheckBox::indicator:checked {image: url(:/checkbox-checked.png);
                                    }
                                    QCheckBox::indicator:checked:hover {image: url(:/checkbox-checked_hover.png);
                                    }
                                    QCheckBox::indicator:checked:pressed {image: url(:/checkbox-checked_pressed.png);
                                    }
                                    

                                    4.運行程序, 觀察效果

                                    小結:

                                    要點說明
                                    ::indicator子控件選擇器,選中 checkbox 中的對鉤部分
                                    :hover偽類選擇器,選中鼠標移動上去的狀態
                                    :pressed偽類選擇器,選中鼠標按下的狀態
                                    :checked偽類選擇器,選中 checkbox 被選中的狀態
                                    :unchecked偽類選擇器,選中 checkbox 未被選中的狀態
                                    width設置子控件寬度,對于普通控件無效 (普通控件使用 geometry 方式設定尺寸)
                                    height設置子控件高度,對于普通控件無效 (普通控件使用 geometry 方式設定尺寸)
                                    image設置子控件的圖片,像 QSpinBox, QComboBox 等可以使用這個屬性來設置子控件的圖片

                                    1.8.3 單選框

                                    代碼示例: 自定義單選框

                                    1.創建 resource.qrc 文件, 并導入以下圖片

                                    • 使用黑色作為默認形態
                                    • 使用藍色作為 hover 形態
                                    • 使用紅色作為 pressed 形態

                                      2.在界面上創建兩個單選按鈕

                                        3.在 Qt Designer 中編寫樣式

                                        此處為了讓所有 QRadioButton 都能生效,把樣式設置在 Widget 上了,并且使用后代選擇器選中了 QWidget 里面的 QRadioButton。

                                        QWidget QRadioButton {font-size: 20px;
                                        }
                                        QWidget QRadioButton::indicator {width: 20px;height: 20px;
                                        }
                                        QWidget QRadioButton::indicator:unchecked {image: url(:/radio-unchecked.png);
                                        }
                                        QWidget QRadioButton::indicator:unchecked:hover {image: url(:/radio-unchecked_hover.png);
                                        }
                                        QWidget QRadioButton::indicator:unchecked:pressed {image: url(:/radio-unchecked_pressed.png);
                                        }
                                        QWidget QRadioButton::indicator:checked {image: url(:/radio-checked.png);
                                        }
                                        QWidget QRadioButton::indicator:checked:hover {image: url(:/radio-checked_hover.png);
                                        }
                                        QWidget QRadioButton::indicator:checked:pressed {image: url(:/radio-checked_pressed.png);
                                        }
                                        
                                          要點說明
                                          ::indicator子控件選擇器,選中 radioButton 中的對鉤部分
                                          :hover偽類選擇器,選中鼠標移動上去的狀態
                                          :pressed偽類選擇器,選中鼠標按下的狀態
                                          :checked偽類選擇器,選中 radioButton 被選中的狀態
                                          :unchecked偽類選擇器,選中 radioButton 未被選中的狀態
                                          width設置子控件寬度,對于普通控件無效 (普通控件使用 geometry 方式設定尺寸)
                                          height設置子控件高度,對于普通控件無效 (普通控件使用 geometry 方式設定尺寸)
                                          image設置子控件的圖片,像 QSpinBox, QComboBox 等可以使用這個屬性來設置子控件的圖片

                                          1.8.4輸入框

                                          代碼示例: 自定義單行編輯框

                                          1.在界面上創建一個單行編輯框

                                          2.在 Qt Designer 中編寫樣式

                                            QLineEdit {border-width: 1px;border-radius: 10px;border-color: rgb(58, 58, 58);border-style: inset;padding: 0 8px;color: rgb(255, 255, 255);background:rgb(100, 100, 100);selection-background-color: rgb(187, 187, 187);selection-color: rgb(60, 63, 65);
                                            }
                                            

                                              3.執行程序觀察效果

                                              屬性說明
                                              border-width設置邊框寬度
                                              border-radius設置邊框圓角
                                              border-color設置邊框顏色
                                              border-style設置邊框風格
                                              padding設置內邊距
                                              color設置文字顏色
                                              background設置背景顏色
                                              selection-background-color設置選中文字的背景顏色
                                              selection-color設置選中文字的文本顏色

                                              1.8.5 列表

                                              代碼示例: 自定義列表框

                                              1.在界面上創建一個 ListView

                                              2.編寫代碼

                                                QListView::item:hover {background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FAFBFE, stop: 1 #DCDEF1);
                                                }
                                                QListView::item:selected {border: 1px solid #6a6ea9;background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #6a6ea9, stop: 1 #888dd9);
                                                }

                                                  3.執行程序, 觀察效果

                                                  要點說明
                                                  ::item選中 QListView 中的具體條目
                                                  :hover選中鼠標懸停的條目
                                                  :selected選中某個被選中的條目
                                                  background設置背景顏色
                                                  border設置邊框
                                                  qlineargradient設置漸變色

                                                  qlineargradient 有 6 個參數

                                                  x1, y1: 標注了一個起點

                                                  x2, y2: 標注了一個終點.

                                                  這兩個點描述了一個 “方向”

                                                  stop0 和 stop1 描述了兩個顏色. 漸變過程就是從 stop0 往 stop1 進行漸變的

                                                  例如:

                                                  • x1: 0, y1: 0, x2: 0, y2: 1 就是垂直方向從上向下 進行顏色漸變
                                                  • x1: 0, y1: 0, x2: 1, y2: 0 就是水平方向從左向右 進行顏色漸變
                                                  • x1: 0, y1: 0, x2: 1, y2: 1 就是從左上往右下方向 進行顏色漸變

                                                  1.8.6 菜單欄

                                                  1.創建菜單欄

                                                  2.編寫樣式

                                                    QMenuBar {background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 lightgray, stop:1 darkgray);spacing: 3px; /* spacing between menu bar items */
                                                    }
                                                    QMenuBar::item {padding: 1px 4px;background: transparent;border-radius: 4px;
                                                    }
                                                    QMenuBar::item:selected { /* when selected using mouse or keyboard */background: #a8a8a8;
                                                    }
                                                    QMenuBar::item:pressed {background: #888888;
                                                    }
                                                    QMenu {background-color: white;margin: 0 2px; /* some spacing around the menu */
                                                    }
                                                    QMenu::item {padding: 2px 25px 2px 20px;border: 3px solid transparent; /* reserve space for selection border */
                                                    }
                                                    QMenu::item:selected {border-color: darkblue;background: rgba(100, 100, 100, 150);
                                                    }
                                                    QMenu::separator {height: 2px;background: lightblue;margin-left: 10px;margin-right: 5px;
                                                    }

                                                      3.執行程序, 觀察效果

                                                      要點說明
                                                      QMenuBar::item選中菜單欄中的元素
                                                      QMenuBar::item:selected選中菜單來中的被選中的元素
                                                      QMenuBar::item:pressed選中菜單欄中的鼠標點擊的元素
                                                      QMenu::item選中菜單中的元素
                                                      QMenu::item:selected選中菜單中的被選中的元素
                                                      QMenu::separator選中菜單中的分割線

                                                      1.8.7登錄界面

                                                      給界面創建元素

                                                      此時界面布局不夠整齊、不夠合理,通過布局管理器進行調整

                                                      添加垂直布局管理器

                                                      此時會發現各個控件大小不合理

                                                      設置Line Edit最大高度和最小高度都為40,此時Line Edit的高度固定為40像素

                                                      同樣設置QPushButton的寬度和高度設置為90*30像素

                                                      給窗口設置一個背景

                                                      直接想法,是給頂層窗口設置背景圖,但是Qt存在限制,直接給頂層窗口設置背景會失效。

                                                      給頂層窗口創建一個同樣大小的QFrame的子對象,QFrame相對于QWidget提供了更多的功能,比如設置形狀、設置樣式。

                                                      在Qt中除了background-image設置背景圖除了,還有border-image來設置背景圖,推建使用border-image來設置背景圖設置背景圖,通過border-image設置的背景圖根據窗口大小同步的變化,而background-image設置背景圖是固定大小。

                                                      設置背景后的界面效果

                                                      設置了背景圖還不夠,針對上面的控件還需要在樣式上進一步設計。

                                                      這里統一在QWidget上進行樣式的修改

                                                      1.設置輸入框樣式

                                                      編寫 QSS 代碼

                                                        2.設置 checkbox 樣式

                                                        背景色使用 transparent 表示完全透明 (應用父元素的背景)

                                                          3.設置按鈕樣式

                                                          4.為了讓用戶明卻輸入的是什么,設置placeholderText屬性

                                                            5.密碼框中的內容默認是不顯示的,設置隱藏

                                                              選擇密碼框,找到echoMode選項,選擇Password

                                                              2.繪圖

                                                              雖然 Qt 已經內置了很多的控件, 但是不能保證現有控件就可以應對所有場景,很多時候我們需要更強的 “自定制” 能力。所謂的 “控件” , 本質上也是通過畫圖的方式畫上去的,控件是對畫圖 API 的進一步封裝,畫圖 API 是控件的底層實現。

                                                              和繪圖相關的類

                                                              說明
                                                              QPainter“繪畫者” 或者 “畫家”,用來繪圖的對象,提供了一系列 drawXXX 方法,可以允許我們繪制各種圖形。
                                                              QPaintDevice“畫板”,描述了 QPainter 把圖形畫到哪個對象上. 像咱們之前用過的 QWidget 也是一種 QPaintDevice (QWidget 是 QPaintDevice 的子類) 。
                                                              QPen“畫筆”,描述了 QPainter 畫出來的線是什么樣的。
                                                              QBrush“畫刷”,描述了 QPainter 填充一個區域是什么樣的。

                                                              繪圖 API 的使用,一般不會在 QWidget 的構造函數中使用, 而是要放到 paintEvent 事件中。

                                                              paintEvent 會在以下情況下被觸發:

                                                              • 控件首次創建
                                                              • 控件被遮擋, 再解除遮擋
                                                              • 窗口最小化,再恢復
                                                              • 控件大小發生變化時
                                                              • 主動調用 repaint() 或者 update() 方法. (這兩個方法都是 QWidget 的方法)

                                                              2.1繪制線段

                                                              示例1:

                                                              void drawLine(const QPoint &p1, const QPoint &p2);
                                                              參數:
                                                              p1:繪制起點坐標
                                                              p2:繪制終點坐標
                                                              

                                                              示例2:

                                                              void drawLine ( int x1, int y1, int x2, int y2 );
                                                              參數:
                                                              x1,y1:繪制起點坐標
                                                              x2,y2:繪制終點坐標
                                                              

                                                                1.在 “widget.h” 頭文件中聲明繪圖事件

                                                                  2.在 “widget.cpp” 文件中重寫 paintEvent() 方法

                                                                  實現效果如下:

                                                                  2.2繪制矩形

                                                                  void QPainter::drawRect(int x, int y, int width, int height);
                                                                  參數:
                                                                  x:窗口橫坐標;
                                                                  y:窗口縱坐標;
                                                                  width:所繪制矩形的寬度;
                                                                  height:所繪制矩形的高度;
                                                                  

                                                                  2.3 繪制圓形

                                                                  void QPainter::drawEllipse(const QPoint &center, int rx, int ry)
                                                                  參數:
                                                                  center:中心點坐標
                                                                  rx:橫坐標
                                                                  ry:縱坐標
                                                                  

                                                                  實現效果:

                                                                  2.4 繪制文本

                                                                  QPainter類中不僅提供了繪制圖形的功能,還可以使用drawText() 函數來繪制文字,也可以使用setFont() 設置字體等信息。

                                                                  實現效果如下:

                                                                  2.5 設置畫筆

                                                                  QPainter 在繪制時,是有一個默認的畫筆的。在使用時也可以自定義畫筆。在 Qt 中,QPen類中定義

                                                                  了 QPainter 應該如何繪制形狀、線條和輪廓。同時通過 QPen類 可以設置畫筆的線寬、顏色、樣式、

                                                                  畫刷等。

                                                                  畫筆的顏色可以在實例化畫筆對象時進行設置,畫筆的寬度是通過 setWidth() 方法進行設置,畫筆的

                                                                  風格是通過setStyle()方法進行設置,設置畫刷主要是通過 setBrush() 方法。

                                                                  • 設置畫筆顏色:QPen::QPen(const QColor &color) 畫筆的顏色主要是通過 QColor 類設置;
                                                                  • 設置畫筆寬度:void QPen::setWidth(int width)
                                                                  • 設置畫筆風格:void QPen::setStyle(Qt::PenStyle style)

                                                                  畫筆的風格有:

                                                                  實現效果如下:

                                                                  2.6 設置畫刷

                                                                  在 Qt 中,畫刷是使用 QBrush類 來描述,畫刷大多用于填充。QBrush定義了QPainter的填充模式,具有樣式、顏色、漸變以及紋理等屬性。

                                                                  畫刷的格式中定義了填充的樣式,使用 Qt::BrushStyle 枚舉,默認值是 Qt::NoBrush,也就是不進行任何填充。可以通過 Qt 助手查找畫刷的格式。

                                                                  實現效果:

                                                                  2.7繪制圖片

                                                                  其實繪制圖片本質上是將圖片顯示到控件上。

                                                                  2.7.1繪制基礎圖片

                                                                  2.7.2圖片旋轉

                                                                  2.7.3QImage、QPixmap、QBitmap 和 QPicture的區別

                                                                  Qt 提供了四個類來處理圖像數據:QImage、QPixmap、QBitmap 和 QPicture,它們都是常用的繪圖設備。

                                                                  • QImage主要用來進行 I/O 處理,它對 I/O 處理操作進行了優化,而且可以用來直接訪問和操作像素;
                                                                  • QPixmap 主要用來在屏幕上顯示圖像,它對在屏幕上顯示圖像進行了優化;
                                                                  • QBitmap是 QPixmap 的子類,用來處理顏色深度為1的圖像,即只能顯示黑白兩種顏色;
                                                                  • QPicture 用來記錄并重演 QPainter 命令。

                                                                  本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
                                                                  如若轉載,請注明出處:http://www.pswp.cn/pingmian/92632.shtml
                                                                  繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92632.shtml
                                                                  英文地址,請注明出處:http://en.pswp.cn/pingmian/92632.shtml

                                                                  如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

                                                                  相關文章

                                                                  week1+2+3

                                                                  408 計組 1.基本組成2.數據的表示和運算定點數&#xff1a;把數字分為定點整數和定點小數分開存儲 浮點數&#xff1a;用科學計數法存儲 原碼 -全部取反-> 反碼 反碼 1->補碼 補碼 -符號位取反->移碼帶余除法&#xff1a;設x,m∈Z&#xff0c;m>0則存在唯一的整數q…

                                                                  java8中javafx包缺少報錯

                                                                  今天拉取一個jdk1.8的項目里面有一個代碼用到了javafx&#xff0c;這個我記得是jdk中的包&#xff0c;正常不應該報錯的。然后發現jdk中還真沒有&#xff0c;查了一下是因為版本問題。 Java 8 及之前&#xff1a;Oracle JDK 自帶 JavaFX&#xff0c;OpenJDK 通常不包含Java 9 …

                                                                  day072-代碼檢查工具-Sonar與maven私服-Nexus

                                                                  文章目錄0. 老男孩思想-選對池塘釣美人魚1. 代碼回滾方案2. SonarQube2.1 代碼檢查工具2.2 部署sonarqube2.2.1 軟件要求2.2.2 安裝軟件2.2.3 啟動sonar2.2.4 部署插件2.3 sonar檢查java代碼2.3.1 創建sona項目2.3.2 分析java代碼2.3.3 Jenkins結合sonar檢查代碼2.4 sonar檢查非…

                                                                  【前端基礎】15、列表元素、表格元素、表單元素(注:極其粗略的記載。)

                                                                  一、列表元素 1、什么是列表元素2、有序列表&#xff08;ol、li&#xff09; ol有序列表 直接子元素只能是li。 li列表中的每一項。3、無序列表&#xff08;ul、li&#xff09; ol無序列表 直接子元素只能是li。 li列表中的每一項。4、定義列表&#xff08;dl、dt、dd&#xff…

                                                                  IRFBG30PBF Vishay威世MOSFET場效應管

                                                                  IRFBG30PBF Vishay威世&#xff1a;超快MOSFET 場效應管一、產品定位IRFBG30PBF 是Vishay威世推出的600V/30A N溝道功率MOSFET&#xff0c;采用第五代TrenchFET技術&#xff0c;專為開關電源、電機驅動、新能源逆變器等高功率場景設計。以85mΩ超低導通電阻和超快反向恢復&…

                                                                  【07-AGI的討論】

                                                                  AI ANI&#xff1a;artificial narrow intelligence; 如 智能音箱&#xff1b;自動駕駛汽車&#xff0c;網絡搜索&#xff0c;其他用于專業特定事項的工具&#xff1b; AGI&#xff1a;artificial general intelligence; building AI systems that could do anything a typical…

                                                                  [激光原理與應用-225]:機械 - 3D圖與2D圖各自的作用

                                                                  在機械設計與加工領域&#xff0c;3D圖和2D圖是兩種核心的工程表達方式&#xff0c;它們在產品設計、制造、裝配及維護等環節中扮演不同角色&#xff0c;具有互補性。以下是它們各自的作用及具體應用場景的詳細解析&#xff1a;一、3D圖的作用1. 直觀展示產品全貌三維可視化&am…

                                                                  【從零開始java學習|第一篇】java中的名詞概念(JDK、JVM、JRE等等)

                                                                  目錄 一、核心運行環境三要素&#xff08;JVM/JRE/JDK&#xff09; 二、常用開發指令&#xff08;JDK 自帶工具&#xff09; 三、一些其他概念 四、總結核心邏輯鏈 要入門 Java&#xff0c;理解核心概念之間的關系是基礎。以下是 Java 中最核心的基礎概念、工具及相關名詞的…

                                                                  UVa12345 Dynamic len(set(a[L:R]))

                                                                  [TOC](UVa12345 Dynamic len(set(a[L:R]))) 題目鏈接 UVA - 12345 Dynamic len(set(a[L:R])) 題意 有編號從 0 到 n?1 的 n 個數&#xff0c;有兩種操作&#xff1a; Q L R 詢問編號 L 到編號 R?1 的數中有多少個不同的數字。M X Y 將編號為 X 的數字改為 Y。 你的任務就是…

                                                                  [Ubuntu] VNC連接Linux云服務器 | 實現GNOME圖形化

                                                                  將桌面環境修改為 GNOME 并通過 VNC 遠程訪問的步驟 & TightVNC 的安裝與配置說明&#xff1a;1. 安裝 GNOME 桌面環境 sudo apt update sudo apt install ubuntu-gnome-desktop -y2. 安裝 TightVNC 服務器 sudo apt install tightvncserver -y3. 初始化 VNC Server 并設置…

                                                                  進程、網絡通信方法

                                                                  一、進程間通信(IPC)方法 適用于同一臺主機上的進程間數據交換。 管道(Pipe) 匿名管道:單向通信,僅用于父子進程。 命名管道(FIFO):通過文件系統路徑訪問,支持無親緣關系進程。 消息隊列(Message Queue) 結構化消息(類型+數據),按類型讀取,支持異步通信。…

                                                                  [激光原理與應用-241]:設計 - 266n皮秒深紫外激光器,哪些因素影響激光器紫外光的輸出功率?

                                                                  一、短期穩定性266nm皮秒深紫外激光器紫外光輸出功率的穩定性受非線性晶體性能、光學系統設計、熱管理效果、重復頻率與脈沖能量匹配度、環境干擾控制等因素影響&#xff0c;具體分析如下&#xff1a;1. 非線性晶體性能晶體選擇與狀態&#xff1a;BBO&#xff08;偏硼酸鋇&…

                                                                  Django配置sqllite之外的數據庫

                                                                  當連接到其他數據庫后端時&#xff0c;如 MariaDB、MySQL、Oracle 或 PostgreSQL&#xff0c;將需要額外的連接參數。請參閱下面的 ENGINE 配置&#xff0c;了解如何指定其他數據庫類型。這個例子是針對 PostgreSQL&#xff1a; 在django項目的settings.py文件里&#xff0c;關…

                                                                  銀河通用招人形機器人強化學習算法工程師了

                                                                  人形強化學習算法工程師&#xff08;26屆&#xff09;&#xff08;崗位信息已通過jobleap.cn授權&#xff0c;可在csdn發布&#xff09;銀河通用機器人 北京收錄時間&#xff1a; 2025年08月11日職位描述1. 研發基于深度強化學習的足式機器人運動控制算法&#xff0c;提升機器…

                                                                  使用MongoDB存儲和計算距離

                                                                  一、MongoDB 計算距離的優勢 優勢說明原生地理空間索引支持 2dsphere 索引&#xff0c;高效處理地理坐標查詢&#xff08;毫秒級響應&#xff09;。內置地理計算函數提供 $near、$geoWithin、$geoNear 等操作符&#xff0c;無需手動實現復雜計算。高性能基于B樹索引優化&#…

                                                                  鴻蒙開發-ArkUI中@Type作用詳細解答

                                                                  在鴻蒙&#xff08;HarmonyOS&#xff09;應用開發中&#xff0c;Type 是 ArkUI 框架中用于 類型定義和類型檢查 的關鍵注解&#xff08;裝飾器&#xff09;。它的主要作用是為自定義組件的屬性提供明確的類型約束&#xff0c;確保數據傳遞的類型安全性。 核心作用解析&#xf…

                                                                  MCU中的存儲器映射(Memory Map)

                                                                  MCU中的存儲器映射(Memory Map) 在MCU(微控制器單元)中,存儲器映射(Memory Map)是指將不同類型的存儲器(如Flash、RAM、外設寄存器等)和功能模塊分配到統一的地址空間的過程。這種映射方式使得CPU可以通過訪問特定地址來讀寫數據或控制外設,而無需關心物理存儲介質的…

                                                                  Rust面試題及詳細答案120道(11-18)-- 控制流與函數

                                                                  《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

                                                                  數據結構-排序(2)

                                                                  一、堆排序 &#xff08;借助樹&#xff09;1.利用完全二叉樹構建大頂堆 2.堆頂元素和堆底元素進行交換&#xff0c;堆底元素不再參與構建&#xff0c;剩余元素繼續構建大頂堆3.時間復雜度 O(nlogn)1.完全二叉樹&#xff1a;按照從上到下&#xff0c;從左到右的順序進行排序2.…

                                                                  Qt-信號和槽

                                                                  一.信號和槽概念1. 信號&#xff08;Signal&#xff09;概念&#xff1a;信號是 Qt 對象在狀態發生變化或事件發生時自動發出的通知。比如按鈕被點擊、文本框內容變化、定時器超時等&#xff0c;都會發出相應信號。本質&#xff1a;它只是一個函數聲明&#xff08;沒有函數體&a…