文章目录
- 四、工程分享
一、前言
在Qt中,我们可以使用QSS来定制软件的样式,QSS提供了各种【选择器】、【属性】、【伪状态】等来帮助我们实现这一目的,但是似乎这些都是针对Qt提供的内部类,由于一些特定的需求,我们有些时候需要自定义控件,那自定义的控件不是Qt提供的内部类,能不能用QSS来定制样式呢?答案是可以的,接下来我们就来看看具体的步骤吧!
二、效果展示
三、具体步骤
3.1、自定义继承自QWidget的类
首先我们先正常自定义一个控件类,这个类必须继承自QWidget,因为QSS只对QWidget及其子类有效;
在这里拿很久之前写的时钟控件举例:
#ifndef STYLEDWIDGET_H
#define STYLEDWIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QtMath>
#include <QTimer>
#define PI 3.14
class StyledWidget : public QWidget
{
Q_OBJECT
public:
explicit StyledWidget(QWidget *parent = nullptr);
~StyledWidget();
protected:
void paintEvent(QPaintEvent *);//重写绘制事件函数
void Init_Parameter();//初始化参数函数
void Set_Mask(QPainter *);//设置窗体透明
void Draw_Clock(QPainter *);//绘制时钟
void Draw_Broad(QPainter *);//绘制时钟盘
void Draw_Dial(QPainter *);//绘制刻度盘
void Draw_Text(QPainter *);//绘制刻度值
void Draw_Pointer(QPainter *);//绘制指针
private:
QTimer *timer;//定时器
QPoint Center_pos;//时钟圆心坐标
int R_Edge;//外部圆半径
int R_Inside;//内部圆半径
int R_Center;//中心小圆半径
int R_Pointer;//中心指针圆半径
int Div_Max = 12;//大刻度值
int Div_Min = 5;//小刻度值
float BaseAngle = 270;//基础仰角
int H;//时
int M;//分
int S ;//秒
private:
QColor Color_Edge = QColor(0,0,0,255);//外部圆颜色
QColor Color_Inside = QColor(255,255,255,255);//内部圆颜色
QColor Color_Center = QColor(0,0,0,255);//中心小圆颜色
};
#endif // STYLEDWIDGET_H
#include "styledwidget.h"
#include <QTime>
#include <QDebug>
StyledWidget::StyledWidget(QWidget *parent) : QWidget(parent)
{
this->setMinimumSize(800,800);
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(update()));//定时调用绘制事件函数
timer->start(1000);//开启定时器,执行周期为1秒针
}
StyledWidget::~StyledWidget()
{
}
void StyledWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);//设置抗锯齿
Draw_Clock(&painter);
}
void StyledWidget::Draw_Clock(QPainter *painter)
{
Init_Parameter();
Set_Mask(painter);
Draw_Broad(painter);
Draw_Dial(painter);
Draw_Text(painter);
Draw_Pointer(painter);
}
void StyledWidget::Init_Parameter()
{
Center_pos = QPoint(this->width()/2,this->height()/2);//以窗体中心为圆心
R_Edge = this->height()/2;//以窗体高度的一半为半径
R_Inside = R_Edge-10;
R_Center = 15;
R_Pointer = 6;
QTime Time = QTime::currentTime();//获取当前系统时间
H=Time.hour();//分别设置时、分、秒
M=Time.minute();
S=Time.second();
}
void StyledWidget::Set_Mask(QPainter *painter)
{
painter->save();//保存
QBrush brush = QBrush(Qt::transparent);//设置画刷为透明
painter->setBrush(brush);
painter->fillRect(this->rect(),QColor(0,0,0,0));
painter->restore();//恢复
}
void StyledWidget::Draw_Broad(QPainter *painter)
{
painter->save();
QBrush brush = QBrush(Color_Edge);//绘制外部圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Edge,R_Edge);
brush = QBrush(Color_Inside);//绘制内部圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Inside,R_Inside);
brush = QBrush(Color_Center);//绘制中心小圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Center,R_Center);
painter->restore();
}
void StyledWidget::Draw_Dial(QPainter *painter)
{
painter->save();
for(int Loop = 0; Loop <= Div_Max*Div_Min; Loop++)
{
float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*Loop;//从基础仰角开始绘制的每条刻度线对应的角度
int R = R_Inside-1;
int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
if(Loop % Div_Min == 0)//判断是否为大刻度
{
QPen pen(Qt::black);
pen.setWidth(4);
painter->setPen(pen);
R = R_Inside-20;
}
else //判断是否为小刻度
{
QPen pen(Qt::black);
pen.setWidth(2);
painter->setPen(pen);
R = R_Inside-15;
}
int x_end = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_end = Center_pos.y() + R * sin((Angle / 180) * PI);
painter->drawLine(QPoint(x_start,y_start),QPoint(x_end,y_end));//绘制刻度线
}
painter->restore();
}
void StyledWidget::Draw_Text(QPainter *painter)
{
painter->save();
QPen qPen(Qt::black);
qPen.setWidth(5); //设置画笔的粗细
painter->setPen(qPen);
QFont qFont("楷体",28,QFont::Bold,false);
painter->setFont(qFont);
int Dial_Text = 12;
for(int Loop = 0;Loop < Div_Max;Loop++)
{
if(Dial_Text >12 )
Dial_Text = 1;
int R = R_Inside-60;
float Angle = BaseAngle + (360 / Div_Max )*Loop;
int x = Center_pos.x() + R * cos((Angle / 180) * PI);
int y = Center_pos.y() + R * sin((Angle / 180) * PI);
painter->drawText(QRect(x-20,y-20,80,80),QString::number(Dial_Text++));
}
painter->drawText(Center_pos.x()-60,Center_pos.y()+60,"劳力士");
painter->restore();
}
void StyledWidget::Draw_Pointer(QPainter *painter)
{
painter->save();
QBrush qBrush = QBrush(QColor(Qt::black));
painter->setBrush(qBrush);
QPen qPen(Qt::black);
qPen.setWidth(2); //设置画笔的粗细
painter->setPen(qPen);
//**********绘制秒针***********************************************************************************
float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*S;
float RightAngle = Angle + 90;//右侧角度
float LeftAngle = Angle - 90;//左侧角度
int R = R_Inside-1;
int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
int x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
int y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
int x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
int y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_S[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_S,3);
//**********绘制分针***********************************************************************************
Angle = BaseAngle + (360 / (Div_Max * Div_Min))*M;
RightAngle = Angle + 90;//右侧角度
LeftAngle = Angle - 90;//左侧角度
R = R_Inside-60;
x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_M[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_M,3);
//**********绘制时针***********************************************************************************
Angle = BaseAngle + (360 / Div_Max)*H;
RightAngle = Angle + 90;//右侧角度
LeftAngle = Angle - 90;//左侧角度
R = R_Inside-120;
x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_H[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_H,3);
painter->restore();
}
3.2、自定义类添加自定义属性及接口
//1、原先时钟控件中定义的成员变量(即属性)
private:
QColor Color_Edge = QColor(0,0,0,255);//外部圆颜色
QColor Color_Inside = QColor(255,255,255,255);//内部圆颜色
QColor Color_Center = QColor(0,0,0,255);//中心小圆颜色
//2、添加属性接口
public:
void set_Color_Edge(QColor color);
QColor get_Color_Edge();
void set_Color_Inside(QColor color);
QColor get_Color_Inside();
void set_Color_Center(QColor color);
QColor get_Color_Center();
//=============================================对外接口==============================================
void StyledWidget::set_Color_Edge(QColor color)
{
this->Color_Edge = color;
this->update();
}
QColor StyledWidget::get_Color_Edge()
{
return this->Color_Edge;
}
void StyledWidget::set_Color_Inside(QColor color)
{
this->Color_Inside = color;
this->update();
}
QColor StyledWidget::get_Color_Inside()
{
return this->Color_Inside;
}
void StyledWidget::set_Color_Center(QColor color)
{
this->Color_Center = color;
this->update();
}
QColor StyledWidget::get_Color_Center()
{
return this->Color_Center;
}
//3、添加Q_PROPERTY,暴露属性
Q_PROPERTY(QColor Color_Edge READ get_Color_Edge WRITE set_Color_Edge);
Q_PROPERTY(QColor Color_Inside READ get_Color_Inside WRITE set_Color_Inside);
Q_PROPERTY(QColor Color_Center READ get_Color_Center WRITE set_Color_Center);
3.3、完整的时钟控件代码
#ifndef STYLEDWIDGET_H
#define STYLEDWIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QtMath>
#include <QTimer>
#define PI 3.14
class StyledWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor Color_Edge READ get_Color_Edge WRITE set_Color_Edge);
Q_PROPERTY(QColor Color_Inside READ get_Color_Inside WRITE set_Color_Inside);
Q_PROPERTY(QColor Color_Center READ get_Color_Center WRITE set_Color_Center);
public:
explicit StyledWidget(QWidget *parent = nullptr);
~StyledWidget();
public:
void set_Color_Edge(QColor color);
QColor get_Color_Edge();
void set_Color_Inside(QColor color);
QColor get_Color_Inside();
void set_Color_Center(QColor color);
QColor get_Color_Center();
protected:
void paintEvent(QPaintEvent *);//重写绘制事件函数
void Init_Parameter();//初始化参数函数
void Set_Mask(QPainter *);//设置窗体透明
void Draw_Clock(QPainter *);//绘制时钟
void Draw_Broad(QPainter *);//绘制时钟盘
void Draw_Dial(QPainter *);//绘制刻度盘
void Draw_Text(QPainter *);//绘制刻度值
void Draw_Pointer(QPainter *);//绘制指针
private:
QTimer *timer;//定时器
QPoint Center_pos;//时钟圆心坐标
int R_Edge;//外部圆半径
int R_Inside;//内部圆半径
int R_Center;//中心小圆半径
int R_Pointer;//中心指针圆半径
int Div_Max = 12;//大刻度值
int Div_Min = 5;//小刻度值
float BaseAngle = 270;//基础仰角
int H;//时
int M;//分
int S ;//秒
private:
QColor Color_Edge = QColor(0,0,0,255);//外部圆颜色
QColor Color_Inside = QColor(255,255,255,255);//内部圆颜色
QColor Color_Center = QColor(0,0,0,255);//中心小圆颜色
};
#endif // STYLEDWIDGET_H
#include "styledwidget.h"
#include <QTime>
#include <QDebug>
StyledWidget::StyledWidget(QWidget *parent) : QWidget(parent)
{
this->setMinimumSize(800,800);
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(update()));//定时调用绘制事件函数
timer->start(1000);//开启定时器,执行周期为1秒针
}
StyledWidget::~StyledWidget()
{
}
void StyledWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);//设置抗锯齿
Draw_Clock(&painter);
}
void StyledWidget::Draw_Clock(QPainter *painter)
{
Init_Parameter();
Set_Mask(painter);
Draw_Broad(painter);
Draw_Dial(painter);
Draw_Text(painter);
Draw_Pointer(painter);
}
void StyledWidget::Init_Parameter()
{
Center_pos = QPoint(this->width()/2,this->height()/2);//以窗体中心为圆心
R_Edge = this->height()/2;//以窗体高度的一半为半径
R_Inside = R_Edge-10;
R_Center = 15;
R_Pointer = 6;
QTime Time = QTime::currentTime();//获取当前系统时间
H=Time.hour();//分别设置时、分、秒
M=Time.minute();
S=Time.second();
}
void StyledWidget::Set_Mask(QPainter *painter)
{
painter->save();//保存
QBrush brush = QBrush(Qt::transparent);//设置画刷为透明
painter->setBrush(brush);
painter->fillRect(this->rect(),QColor(0,0,0,0));
painter->restore();//恢复
}
void StyledWidget::Draw_Broad(QPainter *painter)
{
painter->save();
QBrush brush = QBrush(Color_Edge);//绘制外部圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Edge,R_Edge);
brush = QBrush(Color_Inside);//绘制内部圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Inside,R_Inside);
brush = QBrush(Color_Center);//绘制中心小圆
painter->setBrush(brush);
painter->drawEllipse(Center_pos,R_Center,R_Center);
painter->restore();
}
void StyledWidget::Draw_Dial(QPainter *painter)
{
painter->save();
for(int Loop = 0; Loop <= Div_Max*Div_Min; Loop++)
{
float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*Loop;//从基础仰角开始绘制的每条刻度线对应的角度
int R = R_Inside-1;
int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
if(Loop % Div_Min == 0)//判断是否为大刻度
{
QPen pen(Qt::black);
pen.setWidth(4);
painter->setPen(pen);
R = R_Inside-20;
}
else //判断是否为小刻度
{
QPen pen(Qt::black);
pen.setWidth(2);
painter->setPen(pen);
R = R_Inside-15;
}
int x_end = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_end = Center_pos.y() + R * sin((Angle / 180) * PI);
painter->drawLine(QPoint(x_start,y_start),QPoint(x_end,y_end));//绘制刻度线
}
painter->restore();
}
void StyledWidget::Draw_Text(QPainter *painter)
{
painter->save();
QPen qPen(Qt::black);
qPen.setWidth(5); //设置画笔的粗细
painter->setPen(qPen);
QFont qFont("楷体",28,QFont::Bold,false);
painter->setFont(qFont);
int Dial_Text = 12;
for(int Loop = 0;Loop < Div_Max;Loop++)
{
if(Dial_Text >12 )
Dial_Text = 1;
int R = R_Inside-60;
float Angle = BaseAngle + (360 / Div_Max )*Loop;
int x = Center_pos.x() + R * cos((Angle / 180) * PI);
int y = Center_pos.y() + R * sin((Angle / 180) * PI);
painter->drawText(QRect(x-20,y-20,80,80),QString::number(Dial_Text++));
}
painter->drawText(Center_pos.x()-60,Center_pos.y()+60,"劳力士");
painter->restore();
}
void StyledWidget::Draw_Pointer(QPainter *painter)
{
painter->save();
QBrush qBrush = QBrush(QColor(Qt::black));
painter->setBrush(qBrush);
QPen qPen(Qt::black);
qPen.setWidth(2); //设置画笔的粗细
painter->setPen(qPen);
//**********绘制秒针***********************************************************************************
float Angle = BaseAngle + (360 / (Div_Max * Div_Min))*S;
float RightAngle = Angle + 90;//右侧角度
float LeftAngle = Angle - 90;//左侧角度
int R = R_Inside-1;
int x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
int y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
int x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
int y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
int x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
int y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_S[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_S,3);
//**********绘制分针***********************************************************************************
Angle = BaseAngle + (360 / (Div_Max * Div_Min))*M;
RightAngle = Angle + 90;//右侧角度
LeftAngle = Angle - 90;//左侧角度
R = R_Inside-60;
x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_M[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_M,3);
//**********绘制时针***********************************************************************************
Angle = BaseAngle + (360 / Div_Max)*H;
RightAngle = Angle + 90;//右侧角度
LeftAngle = Angle - 90;//左侧角度
R = R_Inside-120;
x_start = Center_pos.x() + R * cos((Angle / 180) * PI);
y_start = Center_pos.y() + R * sin((Angle / 180) * PI);
R = R_Pointer-1;
x_end1 = Center_pos.x() + R * cos(RightAngle * 3.14 / 180);//过圆心的右侧切点
y_end1 = Center_pos.y() + R * sin(RightAngle * 3.14 / 180);
x_end2 = Center_pos.x() + R * cos(LeftAngle * 3.14 / 180);//过圆心的左侧切点
y_end2 = Center_pos.y() + R * sin(LeftAngle * 3.14 / 180);
QPointF qTriangle_H[3] = {QPoint(x_start,y_start),QPoint(x_end1,y_end1),QPoint(x_end2,y_end2)};
painter->drawPolygon(qTriangle_H,3);
painter->restore();
}
//=============================================对外接口==============================================
void StyledWidget::set_Color_Edge(QColor color)
{
this->Color_Edge = color;
this->update();
}
QColor StyledWidget::get_Color_Edge()
{
return this->Color_Edge;
}
void StyledWidget::set_Color_Inside(QColor color)
{
this->Color_Inside = color;
this->update();
}
QColor StyledWidget::get_Color_Inside()
{
return this->Color_Inside;
}
void StyledWidget::set_Color_Center(QColor color)
{
this->Color_Center = color;
this->update();
}
QColor StyledWidget::get_Color_Center()
{
return this->Color_Center;
}
3.4、添加qss文件
不懂怎么使用qss文件的可以参考:学习QT之QSS的使用
新建qss文件,在其内添加qss代码,QSS中使用自定义的属性设置样式需要使用qproperty-属性
的形式;
为了查看效果,我新建了三个qss文件:
【qss1.qss】
StyledWidget {
qproperty-Color_Edge: black;
qproperty-Color_Inside: white;
qproperty-Color_Center: black;
}
【qss2.qss】
StyledWidget {
qproperty-Color_Edge: #FF8247;
qproperty-Color_Inside: #FFC1C1;
qproperty-Color_Center: #FF6A6A;
}
【qss3.qss】
StyledWidget {
qproperty-Color_Edge: #00FF00;
qproperty-Color_Inside: #00FF7F;
qproperty-Color_Center: #FFFACD;
}
3.5、切换qss
按下A键切换【qss1.qss】,按下B键切换【qss2.qss】,按下C键切换【qss3.qss】
void MainWindow::Set_QSS(QString qssPath)//设置样式
{
QFile file(qssPath);
file.open(QFile::ReadOnly);
QString styleSheet = tr(file.readAll());
this->setStyleSheet(styleSheet);
file.close();
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if(event->key()==Qt::Key_A) {
qDebug()<<"Key_A";
Set_QSS(":/QSS/Resources/qss1.qss");
}
if(event->key()==Qt::Key_B) {
qDebug()<<"Key_B";
Set_QSS(":/QSS/Resources/qss2.qss");
}
if(event->key()==Qt::Key_C) {
qDebug()<<"Key_C";
Set_QSS(":/QSS/Resources/qss3.qss");
}
}
四、工程分享
链接:https://pan.baidu.com/s/1Jq0AQqMJygo9DVZfk0dbgQ 提取码:lqh4