QStyle(1):自定義部件外觀基礎

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();  }

在這裏插入圖片描述

本文作者:黃邦勇帥(原名:黃勇)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章