QT用代码实现QSlider样式自定义

文章介绍了如何通过派生QSlider类并重写paintEvent方法来实现一个具有自定义样式的滚动条,包括设置滑块样式、刻度样式以及添加刻度点。同时,展示了使用QPainter进行图形绘制以创建刻度线和刻度值的方法。

一、理论概述(略,百度大把)

二、实现效果

三、实现过程:

方法1:派生与类QSlider实现。

**样式设置(可以用setSytlesheeet在构造函数实现,这里直接写下样式里偷懒一下)

QSlider::groove:horizontal {

border: 1px solid gray;

height: 2px;

left: 8px;

right: 8px;

}

QSlider::handle:horizontal {

border: 1px solid gray;

background:white;

border-radius: 10px;

width: 20px;

height:20px;

margin: -10px;

}

QSlider::add-page:horizontal{

background: rgb(189, 189, 189);

}

QSlider::sub-page:horizontal{

background: rgb(0, 0, 255);

}

具体实现代码如下:

*************************************.h*******************************

#ifndef SCROLLBAR_H

#define SCROLLBAR_H

#include <QWidget>

#include<QSlider>

#define DEF_MIN_RANGE 80

#define DEF_MAX_RANGE 100

class scrollBar : public QSlider

{

Q_OBJECT

public:

explicit scrollBar(QWidget *parent = nullptr);

~scrollBar();

void addScale(int value);

void setupView();

signals:

protected:

void paintEvent(QPaintEvent *event) override;

private:

QVector<int> m_scales; //刻度列表

};

#endif // SCROLLBAR_H

*************************************.cpp*******************************

#include "scrollbar.h"

#include<QLabel>

#include<QSlider>

#include<QPainter>

#include<QPen>

#include <QStyleOptionSlider>

#include<QColor>

#include<QBrush>

scrollBar::scrollBar(QWidget *parent) : QSlider(parent)

{

// setupView();

m_scales.push_back(5);

m_scales.push_back(10);

m_scales.push_back(15);

m_scales.push_back(20);

m_scales.push_back(25);

m_scales.push_back(30);

m_scales.push_back(35);

m_scales.push_back(40);

}

scrollBar::~scrollBar()

{

}

void scrollBar::setupView()

{

//设置水平还是垂直滑动条,默认为垂直

this->setOrientation(Qt::Horizontal);

// for(int num = 0 ;num<10;num++)

// {

// QLabel *point = new QLabel(this);

// point->setFixedSize(30, 30);

// //穿透属性:如果滑动条与刻度点重合,当你点击滑动条的时候,防止按压到刻度点,所以给刻度点设置穿透属性,你只能点击到滑动条。

// point->setAttribute(Qt::WA_TransparentForMouseEvents, true);

// point->setStyleSheet("background-color: rgb(91, 154, 212);"

// "border-radius: 15px;");

// //point->set

// point->move(30*(num+1)+30*num, 70);

// }

//设置范围

/*

this->setRange(DEF_MIN_RANGE, DEF_MAX_RANGE);

setFocusPolicy(Qt::StrongFocus);

//键盘左右键的步进值

this->setSingleStep(1);

//鼠标点击的步进值

this->setPageStep(5);

for(int num = 0 ;num<10;num++)

{

QLabel *point = new QLabel(this);

point->setFixedSize(30, 30);

//穿透属性:如果滑动条与刻度点重合,当你点击滑动条的时候,防止按压到刻度点,所以给刻度点设置穿透属性,你只能点击到滑动条。

point->setAttribute(Qt::WA_TransparentForMouseEvents, true);

point->setStyleSheet("background-color: rgb(91, 154, 212);"

"border-radius: 15px;");

//point->set

point->move(30*(num+1)+30*num, 70);

}

*/

//this->set ->setTickPosition(QSlider::TicksAbove);

//this->setStyleSheet("background:rgb(20,20,20,90%);");

//add begin

/*

this->setStyleSheet("QScrollBar:horizontal {\

border: 0px solid grey;\

border-radius:10px;\

background: #2c3e50;\

height: 15px;\

margin: 0px 20px 0 20px;\

}\

QScrollBar::handle:horizontal{\

background: #FFFFFF;\

border-radius: 15px;\

min-width:30px;\

}\

QScrollBar::add-page,\

QScrollBar::sub-page{\

background: transparent;\

}\

QScrollBar::add-line:horizontal {\

border: 0px solid grey;\

border-radius:10px;\

background: #2c3e50;\

width: 0px;\

subcontrol-position: right;\

subcontrol-origin: margin;\

}\

QScrollBar::sub-line:horizontal {\

border: 0px solid grey;\

border-radius:10px;\

background: rgb(20,20,20,90%);\

width: 0px;\

subcontrol-position: left;\

subcontrol-origin: margin;\

}\

QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal{\

border: 1px solid grey;\

width: 3px;\

height: 3px;\

background:rgb(20,20,20,90%);\

}\

QScrollBar::add-page:horizontal {\

background:rgba(146,186,255,0.8);\

}\

QScrollBar::sub-page:horizontal {\

background:rgba(22,93,255,1);\

}\

");

//add end

*/

}

void scrollBar::paintEvent(QPaintEvent *event)

{

QSlider::paintEvent(event);

/* 设置刻度路径 */

QPainterPath path; //刻度路径

QPainterPath textPath; //刻度值的文字路径

QPainterPath shortPath;

struct pos{

QPointF circlePos;

unsigned char drawType;

};

QVector<pos> scirclePos;

scirclePos.clear();

QStyleOptionSlider option;

initStyleOption(&option);

auto r = style()->proxy()->subControlRect(QStyle::CC_Slider, &option, QStyle::SC_SliderGroove, this);

int startX = r.x(); //进度条起始位置的x坐标

int centerY = r.y(), length = r.width() - 1;

double eachValueSpan = (double)length / (maximum() - minimum());

//add begin

path.moveTo(startX, centerY+13);

path.lineTo(startX, centerY + 20);

QString text = QString::number(0);

int textWidth = fontMetrics().width(text);

int textheight = fontMetrics().height();

textPath.addText(startX - textWidth / 2.0, height() - textheight / 2.0, font(), text);

textPath.addText(startX - textWidth / 2.0, height() - textheight / 2.0, font(), text);

float fInterval = eachValueSpan*5.0/5;

//add end

for (int value : m_scales) {

int x = startX + eachValueSpan * (value - minimum());

for(int segment = 0 ;segment<4;segment++)

{

shortPath.moveTo(x-(segment+1)*fInterval,centerY+13) ;

shortPath.lineTo(x-(segment+1)*fInterval,centerY+15);

qDebug("x = %i",(int)(x-(segment+1)*fInterval));

}

/* 添加刻度 */

path.moveTo(x, centerY+13);

path.lineTo(x, centerY + 20);

int tmpValue = this->value();

pos tmpPos;

tmpPos.circlePos.setX(x);

tmpPos.circlePos.setY(centerY+20);

if(value==tmpValue)

{

tmpPos.drawType = 0x01 ;

}else if(value <tmpValue)

{

tmpPos.drawType = 0x02;

}

else

{

tmpPos.drawType = 0 ;

}

scirclePos.push_back(tmpPos);

/* 添加刻度值 */

// QString text = QString::number(value);

// int textWidth = fontMetrics().width(text);

// int textheight = fontMetrics().height();

text = QString::number(value);

textWidth = fontMetrics().width(text);

textheight = fontMetrics().height();

textPath.addText(x - textWidth / 2.0, height() - textheight / 2.0, font(), text);

}

/* 绘制路径 */

QPainter painter(this);

QPen pen;

pen.setColor(Qt::gray);

pen.setWidth(2);

painter.setPen(pen);

painter.drawPath(path);

pen.setWidth(1);

painter.setPen(pen);

painter.drawPath(shortPath);

pen.setColor(Qt::black);

pen.setWidth(1);

painter.setPen(pen);

painter.drawPath(textPath);

pen.setWidth(1);

pen.setColor(Qt::blue);

QBrush brush;

brush.setColor(QColor(189, 189, 189,1));

painter.setBrush(Qt::blue);//设置画刷,如果不画实现的直接把Brush设置为setBrush(Qt::NoBrush);

painter.setPen(pen);

//painter.setBrush(brush);

//painter.setPen(pen);

// painter.setBrush(brush);

painter.drawEllipse(startX-5,centerY-3,10,10);

for(int n = 0 ;n<scirclePos.size();n++)

{

pen.setWidth(1);

pen.setColor(Qt::gray);

//brush.setColor(QColor(189, 189, 189,1));

painter.setBrush(Qt::gray);//设置画刷,如果不画实现的直接把Brush设置为setBrush(Qt::NoBrush);

painter.setPen(pen);

if(scirclePos.at(n).drawType == 0x01)

{

continue;

// pen.setWidth(1);

// pen.setColor(Qt::blue);

// //brush.setColor(QColor(189, 189, 189,1));

// painter.setBrush(Qt::blue);//设置画刷,如果不画实现的直接把Brush设置为setBrush(Qt::NoBrush);

// painter.setPen(pen);

}

if(scirclePos.at(n).drawType == 0x02)

{

pen.setWidth(1);

pen.setColor(Qt::blue);

//brush.setColor(QColor(189, 189, 189,1));

painter.setBrush(Qt::blue);//设置画刷,如果不画实现的直接把Brush设置为setBrush(Qt::NoBrush);

painter.setPen(pen);

}

painter.drawEllipse(scirclePos.at(n).circlePos.x()-5,scirclePos.at(n).circlePos.y()-3-20,10,10);

}

}

方法二:利用继承于QScrollBar实现

实现思想:在QPainter中动态生成QLabel,然后通过控件的组合拼装。

*******************.H************************************************

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE

namespace Ui { class MainWindow; }

QT_END_NAMESPACE

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

MainWindow(QWidget *parent = nullptr);

~MainWindow();

private:

QList<QRect> rectList;

int showSize=20; //页面显示20位

float scale=1;

QPoint m_clickPoint;

bool m_bClick=false;

protected:

void paintEvent(QPaintEvent *event);

private:

Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

*************************************************.cpp************************************************

#include "mainwindow.h"

#include "ui_mainwindow.h"

#include<QLabel>

#include<QPainter>

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

, ui(new Ui::MainWindow)

{

ui->setupUi(this);

this->resize(800,600);

ui->horizontalScrollBar->move(20,80);

int k=0;

int i_size=(this->width()/showSize);

for(int i=0;i<100;i++) //创建100个数字

{

QRect rect(k,100,0.1,10);

rectList.append(rect);

k=k+i_size;

}

//QLabel充当刻度点

for(int num = 0 ;num<10;num++)

{

QLabel *point = new QLabel(this);

point->setFixedSize(30, 30);

//穿透属性:如果滑动条与刻度点重合,当你点击滑动条的时候,防止按压到刻度点,所以给刻度点设置穿透属性,你只能点击到滑动条。

point->setAttribute(Qt::WA_TransparentForMouseEvents, true);

point->setStyleSheet("background-color: rgb(91, 154, 212);"

"border-radius: 15px;");

point->move(30*(num+1)+30*num, 70);

}

// //QLabel充当刻度点

// QLabel *point1 = new QLabel(this);

// point->setFixedSize(6, 6);

// //穿透属性:如果滑动条与刻度点重合,当你点击滑动条的时候,防止按压到刻度点,所以给刻度点设置穿透属性,你只能点击到滑动条。

// point1->setAttribute(Qt::WA_TransparentForMouseEvents, true);

// point1->setStyleSheet("background-color: rgb(91, 154, 212);"

// "border-radius: 3px;");

// point1->move(100, 100);

// QLabel *point3 = new QLabel(this);

// point3->setFixedSize(QSize(25,25));

// point3->setStyleSheet("background-color: white;"

// "color: black;");

// point3->setAlignment(Qt::AlignCenter);

// point3->setText("1");

// point3->setVisible(true);

// point3->move(150, 150);

}

MainWindow::~MainWindow()

{

delete ui;

}

void MainWindow::paintEvent(QPaintEvent *event)

{

QPainter painter(this);

int K=0; //设置值显示的位置

for(int i=0;i<rectList.size();i++)

{

float value = qRound(showSize+(i-showSize)*scale);

if(value<0||value>100) //100和0分别为最大值和最小值

{

continue ;

}

painter.drawRect(rectList[K]);

QString strValue = tr("%1").arg(value);

int fontWidth = fontMetrics().width(strValue)/2;

painter.drawText(QPointF(rectList[K].x()-fontWidth,125/*7+15*/),strValue);

K++;

// painter.drawRect(rectList[i]);

// QString strValue = tr("%1").arg(value);

// int fontWidth = fontMetrics().width(strValue)/2;

// painter.drawText(QPointF(rectList[i].x()-fontWidth,7+15),strValue);

}

}

备注:首先要在桌面上拖入QScrollBar控件

#课程服务在线答疑:本课程设有专门的讨论留言区,学习中遇到任何问题,直接给老师留言即可,老师都会及时进行回复。远程协助:如果遇到复杂问题,老师还可进行远程协助,这个一般可不是一两百元的课程就能享受到的。源码分享:为了让大家更好的进行项目实战,老师还将课程中涉及到的所有源码分享给学员,按照视频中的提示进行下载即可。 在CSDN分享C++ Qt开发知识已经有6年了,感谢众多博友对我的支持,了解到很多人对Qt的使用还是有些困扰,例如Qt环境搭建,Qt布局的使用,如何使用Qt编写复杂的界面,如何自定义非标控件,Qt如何和Web交互,Qt和后台接口如何交互等;经过这几年的整理,我决定出这套《Qt高级开发视频教程》,带领大家学习Qt高级开发知识,学习如何使用Qt开发企业级别的项目;通过本课程的学习,大家将会达到企业招聘的中高级要求。 为了照顾零基础学员,本课程第一章会介绍Qt环境搭建、QtCreator / VS2019的基本使用方法,Qt整体架构、Qt信号机制,Qt内存管理等知识。即使没有Qt开发的学习经验,也能跟着课程顺利学习。课程核心知识点地图如下:课程每章核心知识点介绍如下:第一章:介绍Qt环境搭建、QtCreator / VS2019的基本使用方法,Qt整体架构、Qt信号机制,Qt内存管理等知识。第二章:了解到很多学员对于Qt界面布局很不熟悉,将会详细介绍Qt设计器布局,以及如何C++代码手写布局,从常见的企业级项目入手,带领大家学会各种布局的实现,例如WPS、腾讯会议、优酷、迅雷等界面的实现;界面布局会了,这是企业项目开发的第一步,还有更重要的无边框窗口,如何设计一个合理的无边框窗口很重要,第三/四章:详细介绍如何实现一个无边框窗口,如何自定义标题栏,如何实现拖拽拉伸;第四章将会介绍如何自定义非标控件,优化Qt界面。第五章:介绍Qt web混合编程,一个商用项目,必然会涉及到web交互,这也是很多Qt开发者的弱项,这一章讲详细介绍C++ Qt web混合开发。第六章:既然是做企业级项目,必然需要和后台交互,http编程也是必要的,将详细介绍http编程,用户注册,登录,后台接口请求等知识;通过第五、六章的学习,将会是你的Qt开发技术更上一层楼。第七章:介绍Qt并发编程,耗时任务处理,进程调用等知识。第八、九章:讲解 Qt 比较重要的知识,图形视图结构,以及MVD模式;通过这两章的学习,大家会对图形视图有更好的了解。第十章:本章是独立章节,主要介绍Qt中一些特殊技巧,项目编译,dpi适配、多语言等知识。第十一章:是我们的企业级项目实战:实现一个视频会议客户端,本项目可以进行多人视频通话,直播,桌面分享等功能,本项目我会从零开始,进行项目搭建,功能调试,bug fixed, 带领大家做一个企业级项目。 希望通过本课程的学习,大家的C++ Qt开发技术能有质的飞越,能找到自己心仪的工作。 课程中如果讲的不对的地方,请大家指出,我及时修正,我也只是一个普通开发者,也不是所有的技术都会,尽我所能,把我所会的教给大家,让我们一起为Qt的发展,尽一份绵薄之力。  下面是本课程一些项目的截图:1 可以滑动的设置界面        2 所有图形的绘制      3 视频播放器         4 高仿youku界面        5 视频会议        相信通过本课程的学习,大家有能力实现绝大部分客户端项目,从此用C++ Qt再也不会有难写的界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值