QStyle(1):自定义部件外观基础

QStyle(1):自定义部件外观基础

本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址:
https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q
《C++语法详解》网盘地址:https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

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

在这里插入图片描述

本文作者:黄邦勇帅(原名:黄勇)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/hyongilfmmm/article/details/83238933