最近多在写qt界面,qwidget和qml界面都有在写,由于qml的画图没太多了解,只能先用qquickpainteditem画控件然后放在qml中使用,以又到liudianwu刘大神的控件设计中找了几个,自己实现了发出来,同时添加了动画效果,同时也是为了自己以后方便查看。希望有所帮助。由于这些控件暂时不用,所以我也就没做宽高自适应,望理解。源代码下载地址:https://download.youkuaiyun.com/download/parkchorong/13992830
老规矩,先上图
代码:
这里只展示一个,毕竟一法通,万法通。
#include "carpan.h"
#include <QPainter>
#include <QtMath>
#include <QPropertyAnimation>
#include <QDebug>
CarPan::CarPan(QQuickItem *parent) : QQuickPaintedItem(parent)
{
initAnimation();
setWidth(450);
setHeight(450);
this->r = (this->width() > this->height() ? this->height()/2 : this->width()/2);
this->outoEL = this->r;
resetValue();
}
void CarPan::setPointMode(int mode)
{
qDebug() << __FUNCTION__ ;
curPointMode = mode;
update();
}
void CarPan::setValue(double value)
{
qDebug() << __FUNCTION__ << value;
this->lastValue = this->value;
this->value = value;
// update();
qDebug() << __FUNCTION__ <<lastValue << " " <<value;
initAnimation();
}
void CarPan::setR(double r)
{
this->r = r;
resetValue();
update();
}
double CarPan::getR()
{
this->r = (this->width() > this->height() ? this->height()/2 : this->width()/2);
return this->r;
}
double CarPan::getValue()
{
return this->value;
}
void CarPan::valueChanged(QVariant v)
{
this->value = v.toInt();
update();
}
void CarPan::paint(QPainter *painter)
{
painter->setRenderHint(QPainter::Antialiasing);
painter->translate(this->boundingRect().width()/2, this->boundingRect().height()/2);
initOutE(painter);
initInArc(painter);
initInE(painter);
initPointer(painter);
initTextE(painter);
initShortLine(painter);
initLongLine(painter);
initValueScale(painter);
initOver(painter);
}
void CarPan::initOutE(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(80,80,80)));
painter->drawEllipse(QRect(QPoint(-outoEL, -outoEL), QPoint(outoEL, outoEL)));
painter->restore();
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(60,60,60)));
painter->drawEllipse(QRect(QPoint(-outIEL, -outIEL), QPoint(outIEL, outIEL)));
painter->restore();
}
void CarPan::initInArc(QPainter *painter)
{
painter->save();
QPainterPath pathA;
QPainterPath subPathA;
QPainterPath pathB;
QPainterPath subPathB;
QPainterPath pathC;
QPainterPath subPathC;
pathA.arcTo(-inArcOL, -inArcOL, inArcOL*2, inArcOL*2, -45, 45);
subPathA.arcTo(-inArcIL, -inArcIL, inArcIL*2, inArcIL*2, -45, 45);
pathA -= subPathA;
painter->setBrush(QColor(255, 107, 107));
painter->setPen(Qt::NoPen);
painter->drawPath(pathA);
pathB.arcTo(-inArcOL, -inArcOL, inArcOL*2, inArcOL*2, 0, 45);
subPathB.arcTo(-inArcIL, -inArcIL, inArcIL*2, inArcIL*2, 0, 45);
pathB -= subPathB;
painter->setBrush(QColor(218, 218, 0));
painter->setPen(Qt::NoPen);
painter->drawPath(pathB);
pathC.arcTo(-inArcOL, -inArcOL, inArcOL*2, inArcOL*2, 45, 180);
subPathC.arcTo(-inArcIL, -inArcIL, inArcIL*2, inArcIL*2, 45, 180);
pathC -= subPathC;
painter->setBrush(QColor(24, 189, 155));
painter->setPen(Qt::NoPen);
painter->drawPath(pathC);
painter->restore();
}
void CarPan::initInE(QPainter *painter)
{
painter->save();
painter->setBrush(QColor(100, 100, 100));
painter->setPen(Qt::NoPen);
painter->drawEllipse(QRect(QPoint(-inArcIL, -inArcIL), QPoint(inArcIL, inArcIL)));
painter->restore();
}
void CarPan::initTextE(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(223,105,105)));
painter->drawEllipse(QRect(QPoint(-inTextEOL, -inTextEOL), QPoint(inTextEOL, inTextEOL)));
painter->restore();
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(QColor(250,250,250)));
painter->drawEllipse(QRect(QPoint(-inTextEIL, -inTextEIL), QPoint(inTextEIL, inTextEIL)));
painter->restore();
painter->save();
painter->setPen(Qt::black);
QFont font = painter->font();
font.setPointSize(18);
font.setBold(true);
painter->setFont(font);
painter->drawText(QRect(QPoint(-inTextEIL, -inTextEIL), QPoint(inTextEIL, inTextEIL)), Qt::AlignCenter, QString::number(value));
painter->restore();
}
void CarPan::initShortLine(QPainter *painter)
{
double rotateCount = 270.0 / 100.0;
painter->save();
painter->setPen(Qt::white);
painter->rotate(45);
QLine line(QPoint(shortLineStart,0), QPoint(shortLineStop, 0));
painter->drawLine(line);
for (int i = 0; i < 100 ;i ++) {
painter->rotate(-rotateCount);
painter->drawLine(line);
}
painter->restore();
}
void CarPan::initLongLine(QPainter *painter)
{
double rotateCount = 270.0 / 10.0;
painter->save();
painter->setPen(Qt::white);
QPen pen = painter->pen();
pen.setWidth(2);
painter->setPen(pen);
painter->rotate(45);
QLine line(QPoint(longLineStart,0), QPoint(longtLineStop, 0));
painter->drawLine(line);
for (int i = 0; i < 10 ;i ++) {
painter->rotate(-rotateCount);
painter->drawLine(line);
}
painter->restore();
}
void CarPan::initValueScale(QPainter *painter)
{
painter->save();
painter->setPen(Qt::white);
QFont font = painter->font();
font.setPointSize(14);
font.setBold(true);
painter->setFont(font);
double r = 45;
float x = 0;
float y = 0;
for (int i = 0; i <= 100; i += 10) {
x = longtLineStop * cos(r*M_PI/180);
y = longtLineStop * sin(r*M_PI/180);
switch (i) {
case 0 : painter->drawText(QRect(x, y, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 10 : painter->drawText(QRect(x-5, y-3, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 20 : painter->drawText(QRect(x, y-15, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 30 : painter->drawText(QRect(x, y-24, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 40 : painter->drawText(QRect(x-5, y-30, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 50 : painter->drawText(QRect(x-22, y-31, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 60 : painter->drawText(QRect(x-32, y-23, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 70 : painter->drawText(QRect(x-35, y-20, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 80 : painter->drawText(QRect(x-40, y-15, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
case 90 : painter->drawText(QRect(x-38, y-10, 40,25), Qt::AlignCenter, QString::number((100 - i))); break;
case 100 : painter->drawText(QRect(x-35, y, 40, 25), Qt::AlignCenter, QString::number((100 - i))); break;
}
r -= 27;
}
painter->restore();
}
void CarPan::initPointer(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(223,105,105));
painter->rotate(135 + value*(270.0/100.0));
if (curPointMode == PanPointerMode::POINTMODE) {
QPointF points[3] = {
QPointF(0,12),QPointF(0,-12),QPointF(shortLineStop+5,0)
};
painter->drawPolygon(points,3);
} else if (curPointMode == PanPointerMode::EMODE) {
painter->drawEllipse(QRectF(inArcIL-30,-10,20,20));
} else if (curPointMode == PanPointerMode::THREERECTMODE) {
QPointF points[3] = {
QPointF(inArcIL-23,12),QPointF(inArcIL-23,-12),QPointF(inArcIL-7,0)
};
painter->drawPolygon(points,3);
} else if (curPointMode == PanPointerMode::POINTE) {
painter->drawRoundedRect(QRect(inArcOL-5,-5,longtLineStop-inArcOL+3,10),4,4);
QPointF points[4] = {
QPointF(0,12),QPointF(0,-12),QPointF(longtLineStop,-2),QPointF(longtLineStop,2)
};
painter->drawPolygon(points,4);
}
painter->restore();
}
void CarPan::initOver(QPainter *painter)
{
int radius = outIEL;
painter->save();
painter->setPen(Qt::NoPen);
QPainterPath smallCircle;
QPainterPath bigCircle;
QPainterPath userfulArea;
radius -= 1;
smallCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
radius *= 2;
bigCircle.addEllipse(-radius, -radius + outoEL + outoEL/2, radius * 2, radius * 2);
userfulArea = smallCircle - bigCircle;
QLinearGradient linearGradient(0, -radius / 2, 0, 0);
overColor.setAlpha(100);
linearGradient.setColorAt(0.0, overColor);
overColor.setAlpha(30);
linearGradient.setColorAt(1.0, overColor);
painter->setBrush(linearGradient);
painter->rotate(-20);
painter->drawPath(userfulArea);
painter->restore();
}
void CarPan::initAnimation()
{
m_animation = new QPropertyAnimation(this);
m_animation->setTargetObject(this);
//根据曲线决定变化速度
// if (this->value > this->lastValue) {
// m_animation->setEasingCurve(QEasingCurve::InQuad);
// } else {
// m_animation->setEasingCurve(QEasingCurve::OutQuad);
// }
m_animation->setDuration(500);
m_animation->setStartValue(lastValue);
m_animation->setEndValue(this->value);
connect(m_animation,&QPropertyAnimation::valueChanged,this,&CarPan::valueChanged);
m_animation->start();
}
void CarPan::resetValue()
{
this->outoEL = this->r;
this->outIEL = outoEL - 15;
this->inArcOL = outoEL - 90;
this->inArcIL = inArcOL - 25;
this->inTextEOL = inArcOL - 60;
this->inTextEIL = inTextEOL - 5;
this->shortLineStart = inArcOL + 20;
this->shortLineStop = inArcOL + 34;
this->longLineStart = inArcOL + 16;
this->longtLineStop = inArcOL + 34;
qDebug() << __FUNCTION__ <<outoEL;
}
qml加载代码
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "carpan.h"
#include "arcpan.h"
#include "perpan.h"
#include "halfepan.h"
#include "progpan.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// qApp->setAttribute(Qt::AA_UseOpenGLES);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<CarPan>("CarPan", 1, 0, "CarPan");
qmlRegisterType<ArcPan>("ArcPan", 1, 0, "ArcPan");
qmlRegisterType<PerPan>("PerPan", 1, 0, "PerPan");
qmlRegisterType<HalfEPan>("HalfEPan", 1, 0, "HalfEPan");
qmlRegisterType<ProGPan>("ProGPan",1,0,"ProGPan");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
qml代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 1.4
import CarPan 1.0
import ArcPan 1.0
import PerPan 1.0
import HalfEPan 1.0
import ProGPan 1.0
Window {
visible: true
width: 1000
height: 750
title: qsTr("Hello World")
CarPan{
id:carPan1
width: 450
height: 450
x:0
y: 0
Component.onCompleted: {
setR(220);
}
}
ArcPan{
id:arcPan
width: 450
height: 450
x:500
y: 500
}
HalfEPan{
id:halfEPan
width: 450
height: 450
x:0
y: 500
}
PerPan{
id: perPan
width: 500
height: 500
x: 500
y: 0
Component.onCompleted: {
perPan.setR(235);
}
}
ProGPan{
id: proGPan
width: 500
height: 500
x: 1000
y: 0
Component.onCompleted: {
}
}
ComboBox{
model: ListModel {
ListElement { key: "PointMde"; text: "PointMde"; value: 0 }
ListElement { key: "Emode"; text: "Emode"; value: 1 }
ListElement { key: "ThreeAcMode"; text: "ThreeAcMode"; value: 2 }
ListElement { key: "PointEMode"; text: "PointEMode"; value: 3 }
}
onCurrentIndexChanged: {
carPan1.setPointMode(currentIndex);
halfEPan.setMode(currentIndex);
proGPan.setMode(currentIndex);
}
}
Slider{
minimumValue: 0;
maximumValue: 100
stepSize: 1.0
width: 300
height: 30
anchors.top: carPan1.bottom
anchors.topMargin: 20
onValueChanged: {
carPan1.setValue(value);
arcPan.setValue(value);
perPan.setValue(value);
halfEPan.setValue(value);
console.log(value);
}
}
}