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

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

二、实现效果

三、实现过程:

方法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控件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值