QStyle(1):自定義部件外觀基礎
若對C++語法不熟悉,建議參閱《C++語法詳解》一書,電子工業出版社出版,該書語法示例短小精悍,對查閱C++知識點相當方便,並對語法原理進行了透徹、深入詳細的講解,可確保讀者徹底弄懂C++的原理,徹底解惑C++,使其知其然更知其所以然。此書是一本全面瞭解C++不可多得的案頭必備圖書。
13.1 簡單的使用QStyle類(風格也稱爲樣式)
13.1.1 樣式基礎
QStyle類繼承自QObject,該類是一個抽像類。QStyle類描述了GUI的界面外觀,Qt的內置部件使用該類執行幾乎所有的繪製,以確保使這些部件看起來與本地部件完全相同。
Qt內置了一系列樣式,windows樣式和fusion樣式默認是可用的,而有些樣式需在特定平臺上纔有用,比如windowsxp樣式、windowsvisata樣式、gtk樣式、macintosh樣式等。
使用QStyle的步驟如下
①、使用QStyleFactory::create()靜態函數創建一個QStyle對象。
②、然後使用以下函數把樣式設置到部件或程序中
使用QWidget::setStyle()函數爲某個單個的部件設置樣式。
使用QApplication::setStyle()靜態函數來設置整個程序的樣式。
還可由應用程序的用戶使用-style命令行選項指定樣式,比如
xxx -style windows //使用windows樣式。
若未指定樣式,則Qt將選擇與用戶的平臺或桌面環境最合適的樣式。
示例13.1:QStyle使用示例(效果見圖13-2)
#include<QtWidgets>
int main(int argc, char *argv[]){ QApplication aa(argc,argv);
QWidget w;
QPushButton *pb1=new QPushButton("AAA",&w); pb1->move(22,22);
QPushButton *pb2=new QPushButton("BBB",&w); pb2->move(111,22);
QPushButton *pb3=new QPushButton("CCC",&w); pb2->move(222,22);
pb1->setStyle(QStyleFactory::create("fusion")); //僅按鈕pb1使用系統內置的fusion樣式
aa.setStyle(QStyleFactory::create("windows")); //整個程序使用系統內置的windows樣式
w.resize(444,333); w.show(); return aa.exec(); }
13.1.2 QStyleFactory類及其函數
QStyleFactory類是一個獨立的類,該類主要用於創建一個QStyle對象。
QStyleFactory類的成員函數如下
1)、static QStyle *create(const QString &key); //靜態的
創建並返回與鍵key匹配的QStyle對象,若沒有匹配的QStyle,則返回0。來自樣式插件的樣式和內置樣式都會被匹配。注意:key不區分大小寫。
2)、static QStringList keys(); //靜態的
返回QStyleFactory類可以創建的QStyle的鍵。在創建樣式之前,可以使用qDebug()<<QStyleFactory::keys(); 輸出可創建的QStyle的鍵,然後再使用create()函數創建相應的QStyle。
13.3 自定義部件的外觀
13.3.1 自定義部件外觀基礎
有3種方法可實現自定義界面外觀:重新實現paintEvent()函數、使用QStyle類的繪製函數、子類化QStyle,本小節僅介紹方法1和2的使用方式,方法3見下一節。
1、方法一:重新實現QWidget::paintEvent()函數實現界面外觀的繪製
使用此方法工作量比較大,下面舉一簡單示例對此原理作一說明,以便對後續內容的理解
示例13.3:重新實現paintEvent()函數繪製部件的自定義外觀(效果見圖13-4)
//m.h文件的內容
#ifndef M_H
#define M_H
#include<QtWidgets>
class B:public QPushButton{ Q_OBJECT //子類化QPushButton
public:
bool b; //用於存儲鼠標光標進入或離開按鈕的狀態
bool press; //用於存儲按鈕是否被按下的狀態
B(QString s,QWidget *p1=0):QPushButton(s,p1){ b=0; press=0;}
void mousePressEvent(QMouseEvent *e){
press=1; //保存按鈕被按下的狀態
update(); //更新按鈕,此步不可缺少,否則按鈕外觀不會即時更新。
QPushButton::mousePressEvent(e);};
void mouseReleaseEvent(QMouseEvent *e){ press=0; //按鈕未被按下
update(); QPushButton::mouseReleaseEvent(e); };
void enterEvent(QEvent *event){ b=1; //保存鼠標進入按鈕的狀態
update(); QPushButton::enterEvent(event); }
void leaveEvent(QEvent *event){ b=0; //鼠標離開按鈕的狀態
update(); QPushButton::leaveEvent(event); }
void paintEvent(QPaintEvent *e){ //自定義繪製按鈕的外觀
QPainter pr(this);
QBrush bs(QColor(111,111,111)); //灰色
QPen pn(Qt::DotLine); //此畫筆主要用於繪製焦點框(綠色)
pn.setColor(QColor(1,111,1)); pn.setWidth(4);
QRect r=rect(); //獲取設置的按鈕的大小。
if(b==0){ //若鼠標離開按鈕
pr.fillRect(r,bs); //使用畫刷bs(灰色)填充按鈕的背景,其大小爲r
pr.drawText(r,Qt::AlignCenter,text());} //繪製按鈕上的文本
if(b==1){ pr.fillRect(r,QColor(255,1,1)); //若鼠標進入按鈕,則填充紅色背景
pr.drawText(r,Qt::AlignCenter,text()); } //繪製按鈕上的文本
if(b==1&&press==1){ //鼠標進入按鈕且按鈕被按下
pr.fillRect(r,QColor(222,222,222)); pr.drawText(r,Qt::AlignCenter,text());}
if(b==0&&press==0){ //鼠標離開按鈕且按鈕未被按下
pr.fillRect(r,bs); pr.drawText(r,Qt::AlignCenter,text());}
if(hasFocus()) { //按鈕獲得焦點
pr.setPen(pn);pr.drawRect(r.adjusted(1,1,-2,-2)); } }}; //繪製一個矩形邊框(綠色)
#endif // M_H
//m.cpp文件的內容
#include "m.h"
int main(int argc, char *argv[]){ QApplication aa(argc,argv);
QWidget w;
//使用自定義外觀的按鈕
B *pb1=new B("AAA",&w); pb1->move(22,22); pb1->resize(221,22);
B *pb2=new B("BBB",&w); pb2->move(22,88);
w.resize(444,333); w.show(); return aa.exec(); }
2、方法二:使用QStyle類的繪製函數實現界面外觀的繪製
通常QStyle類的繪製函數需要如下4個參數:
①、一個QStyle枚舉值:用於指定需要繪製什麼類型的圖形元素,比如QStyle::CE_PushButton表示繪製按鈕。
②、一個QStyleOption或其子類對象(樣式選項)。樣式選項包含了需要繪製的圖形元素的所有信息,比如包含了圖形元素的文本、調色板等。根據繪製的內容,樣式需要不同的樣式選項類,比如QStyle::CE_PushButton元素,需要一個QStyleOptionButton類型的參數。
③、一個用於繪製圖形的QPainter
④、執行繪製的QWidget(可選),通常是需要繪製的元素的部件。
⑤、可使用QStylePainter類中的繪製函數代替QStyle類的相應繪製函數,其主要好處是可減少調用函數時的實參個數。
示例13.4:使用QStyle類的繪製函數自定義部件樣式(效果見圖13-5)
//m.h文件的內容
#ifndef M_H
#define M_H
#include<QtWidgets>
class B:public QPushButton{ Q_OBJECT //子類化QPushButton
public: B(QString s,QWidget *p1=0):QPushButton(s,p1){}
void paintEvent(QPaintEvent *e){ //需要重新實現該函數以繪製自定義的按鈕樣式
QPainter pr(this);
QStyleOptionButton psb; //創建一個按鈕樣式選項
psb.rect=rect(); //設置繪製的按鈕的大小,此步不可省略,否則繪製的按鈕將不可見
psb.text="FFF"; //設置按鈕上顯示的文本,要使按鈕被設置爲用戶創建按鈕時的文本
//可使用psb.text=text();代替此語句。
psb.features=QStyleOptionButton::HasMenu; //設置按鈕的樣式爲帶有下拉菜單的按鈕
//獲取該按鈕的樣式對象,並使用該樣式的drawControl()函數繪製按鈕。
style()->drawControl(QStyle::CE_PushButton, &psb, &pr, this);
//也可使用如下代碼繪製,使用實參個數更少
//QStylePainter sp; sp.drawControl(QStyle::CE_PushButton,&psb);
} };
//m.cpp文件的內容
#include "m.h"
int main(int argc, char *argv[]){ QApplication aa(argc,argv);
QWidget w;
B *pb1=new B("AAA",&w); pb1->move(22,22); pb1->resize(221,22);
B *pb2=new B("BBB",&w); pb2->move(22,88);
w.resize(444,333); w.show(); return aa.exec(); }
本文作者:黃邦勇帥(原名:黃勇)