提交 8c81a7c1 编写于 作者: G--H's avatar G--H

add README

上级
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
model-qt/QQuickPaintedItem/ChartView/EVChartView.cpp \
model-qt/QQuickPaintedItem/Dashboard/Dashboard.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
model-qt/QQuickPaintedItem/ChartView/EVChartView.h \
model-qt/QQuickPaintedItem/ChartView/PropertyHelper.h \
model-qt/QQuickPaintedItem/Dashboard/Dashboard.h
此差异已折叠。
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "model-qt/QQuickPaintedItem/ChartView/EVChartView.h"
#include "model-qt/QQuickPaintedItem/Dashboard/Dashboard.h"
//注册到qml中使用
void initRegester()
{
qmlRegisterType<Dashboard>("Zs.model", 1, 0, "Dashboard");
qmlRegisterType<EVChartView>("Zs.model", 1, 0, "EVChartView");
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
initRegester();
const QUrl url(QStringLiteral("qrc:/qml/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();
}
#include "EVChartView.h"
#include <QFontMetrics>
#include <QTime>
EVChartView::EVChartView(QQuickItem *parent):
QQuickPaintedItem(parent),_painter(nullptr)
{
setRenderTarget(QQuickPaintedItem::FramebufferObject);
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::NoButton);
setFlag(ItemAcceptsInputMethod, true);
}
EVChartView::~EVChartView()
{
}
void EVChartView::setLine(QStringList list)
{
//选择时间后 读取数据库后传入
if(list.size()<0) return;
_vLine.clear();
double chartWmin=m_leftDisplayWidth;
double chartWmax=_width-m_rightDisplayWidth;
double chartHmin=m_headerHeight;
double chartHmax=_height-m_bottomHeight;
//反转坐标系 坐标为(0,1)==>转换为(chartWMin+0,chartHMax-1)
double xRate =(double)(chartWmax-chartWmin)/(m_xMax-m_xMin);
//y轴长度
int chartHeightLength = chartHmax-chartHmin;
_xMinTmp=m_xMin;
_xMaxTmp=m_xMax;
_yMinTmp=m_yMin;
_yMaxTmp=m_yMax;
double yRate =((double)chartHeightLength)/(m_yMax-m_yMin);
_xSpace =xRate;
_ySpace=yRate;
if(list.size()>0){
for(int index =0; index<list.size();index++){
if(index==0){
continue;
}
double xStartP=0.f,yStartP=0.f;
double xEndP=0.f,yEndP=0.f;
xStartP=(double)chartWmin+(xRate*((double)index-1-m_xMin));
double ystart= list[index-1].toDouble();
//y匹配坐标系
yStartP=m_headerHeight+yRate*(m_yMax- ystart);
xEndP =(double)chartWmin+xRate*((double)index-m_xMin);
yEndP =(double)m_headerHeight+yRate*(m_yMax-list[index].toDouble());
QLine line =QLine(xStartP,yStartP,xEndP,yEndP);
_vLine.append(line);
}
}
update();
}
void EVChartView::clearLine()
{
_vLine.clear();
_vSeeAreaLine.clear();
update();
}
void EVChartView::startTest()
{
m_xMin = 0;
m_xMax = 1000;
m_yMin = 0;
m_yMax = 100;
QStringList list;
for (int i = 0; i < m_xMax; ++i){
int num = qrand() % 100;
list.append(QString::number(num));
}
setLine(list);
}
void EVChartView::paint(QPainter *painter)
{
_painter = painter;
setFont();
_width =width();
_height=height();
_chartFrame=QRectF(m_leftDisplayWidth,m_headerHeight,_width-m_leftDisplayWidth
-m_rightDisplayWidth,_height-m_headerHeight-m_bottomHeight);
drawHeader();
drawFrame();
drawHorizontalLine();
drawLeftTickLabel();
drawBottomTitle();
drawVlines();
drawLeftLabel();
_painter->setClipRect(_chartFrame);
}
void EVChartView::hoverEnterEvent(QHoverEvent *)
{
}
void EVChartView::hoverLeaveEvent(QHoverEvent *)
{
}
void EVChartView::hoverMoveEvent(QHoverEvent *)
{
}
void EVChartView::wheelEvent(QWheelEvent *)
{
}
void EVChartView::drawHeader()
{
if(m_headerHeight>0 &&!m_headerTxt.isEmpty()){
int widthOfTitle =_painter->fontMetrics().horizontalAdvance(m_headerTxt);//.width(m_headerTxt);//字符串显示的像素大小
int heightOffset = _painter->fontMetrics().height();
if(m_headerTxtColor != "")
_painter->setPen(QColor(m_headerTxtColor)); //设置画笔颜色
_painter->drawText(this->width()/2-widthOfTitle/2,m_headerHeight/2+heightOffset/2,m_headerTxt);
}
}
void EVChartView::drawFrame()
{
QVector<QLine> vLine;
//top
QLine topLine =QLine(m_leftDisplayWidth,m_headerHeight,_width-m_rightDisplayWidth,m_headerHeight);
vLine.append(topLine);
QLine bottomLine =QLine(m_leftDisplayWidth,_height-m_bottomHeight,_width-m_rightDisplayWidth,_height-m_bottomHeight);
vLine.append(bottomLine);
QLine leftLine =QLine(m_leftDisplayWidth,m_headerHeight,m_leftDisplayWidth,_height-m_bottomHeight);
vLine.append(leftLine);
QLine rightLine =QLine(_width-m_rightDisplayWidth,m_headerHeight,_width-m_rightDisplayWidth,_height-m_bottomHeight);
vLine.append(rightLine);
_painter->setPen(QColor("black"));
_painter->drawLines(vLine);
}
void EVChartView::drawHorizontalLine()
{
_yTickCountTmp = m_vTickCount;
QStringList list = stepZoom(_yMinTmp,_yMaxTmp);
_yTickCountTmp =0;
if(list.size()==0) return;
QVector<QLine> vLine;
double space =(_height-m_headerHeight-m_bottomHeight)/(list.size()-1);
for(int index =0; index <list.size()-1;index++){
QLine line =QLine(m_leftDisplayWidth,index*space+m_headerHeight, _width-m_rightDisplayWidth,index*space+m_headerHeight);
vLine.append(line);
}
_painter->drawLines(vLine);
}
void EVChartView::drawLeftTickLabel()
{
_yTickCountTmp =m_vTickCount;
QStringList list = stepZoom(_yMinTmp,_yMaxTmp);
_yTickCountTmp =0;
//算出xlabel的位置
//y 间距
double displayYHeight =double(_height-m_headerHeight-m_bottomHeight);
double space =displayYHeight/(list.size()-1);
//x坐标
// double yLabelPoint =m_leftDisplayWidth;
//匹配y轴长度和单位
// double yLen = ((double)_yMaxTmp- (double)_yMinTmp)/list.size();
for(int index =0; index <list.size();index++){
int heightOffset = _painter->fontMetrics().height();
//字体右对齐 多出负号 或出现位数不一样
QRectF point(0,index*space+m_headerHeight-heightOffset/2,\
m_leftDisplayWidth-10,index*space+m_headerHeight);
_painter->drawText(point,Qt::AlignRight,list.at(list.size()-1-index));
}
}
void EVChartView::drawBottomTitle()
{
//算出xlabel的位置
_yTickCountTmp =m_hTickCount;
QStringList list = stepZoom(_xMinTmp,_xMaxTmp);
_yTickCountTmp =0;
//x 间距
double displayXWidth =double(_width-m_rightDisplayWidth- m_leftDisplayWidth);
double space =displayXWidth/(list.size()-1);
//y 坐标
double yLabelPoint =_height-m_bottomHeight;
//匹配x轴长度和单位
double xLen = ((double)_xMaxTmp- (double)_xMinTmp)/m_hTickCount;
for(int nSpaceIndex =0; nSpaceIndex<list.size();nSpaceIndex++){
int widthOfTitle =_painter->fontMetrics().horizontalAdvance(QString::number(_xMinTmp+xLen*nSpaceIndex));//字符串显示的像素大小
int heightOffset = _painter->fontMetrics().height();
_painter->drawText(m_leftDisplayWidth+space*nSpaceIndex-widthOfTitle/2,yLabelPoint+heightOffset,\
QString::number((int)list.at(nSpaceIndex).toDouble()) );
}
}
void EVChartView::drawLeftLabel()
{
_painter->translate(m_leftDisplayWidth/2-4,_height/2);
_painter->rotate(270);// 旋转
QFont font;
font.setPointSize(11);
font.setFamily("Microsoft YaHei");
font.setLetterSpacing(QFont::AbsoluteSpacing,1);
_painter->setFont(font);
_painter->setPen("black");
_painter->drawText( 0,0,m_leftLabel);
// _painter->rotate(-90);
_painter->translate(_width/2,_height/2);
setFont();
}
void EVChartView::drawVlines()
{
if(_vLine.size()>0){
_painter->setPen("blue");
//将左边的和右边的去掉
if(!_isScale){
_painter->drawLines(_vLine);
}
else{
getSeeAreaLine();
_painter->drawLines(_vSeeAreaLine);
}
}
}
QStringList EVChartView::getCurrentFrame(const QString &strframeValue)
{
return strframeValue.split("&");
}
void EVChartView::pointScale(const QPoint &point)
{
double xMinTmp =_xMinTmp,xMaxTmp =_xMaxTmp,yMaxTmp =_yMaxTmp,yMinTmp =_yMinTmp;
double xWidth =(_width-m_leftDisplayWidth-m_rightDisplayWidth);
double yHeight =_height-m_headerHeight-m_bottomHeight;
//放大后的长宽
double xCurrentScaleWidth =xWidth*getXScaleValue();
double yCurrentScaleHeight =yHeight*getYScaleValue();
//x y位置
double x =point.x()-m_leftDisplayWidth;
double y=point.y()-m_headerHeight;
//x y 与width height比例
double xRate = x/xWidth;
double yRate = y/yHeight;
//宽 左右两边长度,高 上下长度
double xLeftWidth = xCurrentScaleWidth*xRate;
double xRightWidth = xCurrentScaleWidth*((double)1-xRate);
double yTopHeight = yCurrentScaleHeight*yRate;
double yBottomHeight = yCurrentScaleHeight*((double)1-yRate);
//宽坐标 0-24000
double xPointLen =_xMaxTmp-_xMinTmp; double yPointLen =_yMaxTmp-_yMinTmp;
_xMinTmp = (_xMinTmp+ (xLeftWidth-x)*(xPointLen/xCurrentScaleWidth));
_xMaxTmp = _xMaxTmp-(xRightWidth-(xWidth-x))*(xPointLen/xCurrentScaleWidth);
//高坐标 -8-8
// _yMaxTmp = m_yMax- (yTopHeight-y)*(yPointLen/yCurrentScaleHeight);
// _yMinTmp = m_yMin+(yBottomHeight-(yHeight-y))*(yPointLen/yCurrentScaleHeight);
_yMaxTmp =_yMaxTmp -(yTopHeight-y)*(yPointLen/yCurrentScaleHeight);
_yMinTmp =_yMinTmp +(yBottomHeight-(yHeight-y))*(yPointLen/yCurrentScaleHeight);;
if((_xMaxTmp-_xMinTmp)/m_hTickCount<5 ||(_yMaxTmp-_yMinTmp)/m_vTickCount<0.002){
_xMinTmp=xMinTmp;
_xMaxTmp=xMaxTmp;
_yMinTmp=yMinTmp;
_yMaxTmp=yMaxTmp;
}
_isScale=true;
}
void EVChartView::pointNarrow(const QPoint &point)
{
//缩小后刻度
qDebug()<<"缩小前 xMin:"<<_xMinTmp<<" 缩小前 xMax:"<<_xMaxTmp;
double xWidth =(_width-m_leftDisplayWidth-m_rightDisplayWidth);
double yHeight =_height-m_headerHeight-m_bottomHeight;
//放大后的长宽
double xCurrentScaleWidth =xWidth/getXScaleValue();
double yCurrentScaleHeight =yHeight/getYScaleValue();
//x y位置
double x =point.x()-m_leftDisplayWidth;
double y=point.y()-m_headerHeight;
//x y 与width height比例 缩小前比例
double xRate =(_xMaxTmp-_xMinTmp)/xCurrentScaleWidth;
double yRate = (_yMaxTmp-_yMinTmp)/yCurrentScaleHeight;
//放大后x 坐标位置 = 左边扩展的坐标+缩小后的坐标位置
double xNarrowAddWidth =xWidth-xCurrentScaleWidth; //增加的width
//左边加了多少
double xLeft = (x/xWidth) *xNarrowAddWidth;
_xMinTmp=_xMinTmp -xRate*xLeft ;
//右边
double xRight = xNarrowAddWidth- (x/xWidth) *xNarrowAddWidth;
_xMaxTmp=_xMaxTmp +xRate*xRight ;
//缩小后 y坐标的位置 =上扩展坐标+缩小后的坐标位置
double yNarrowAddWidth =yHeight-yCurrentScaleHeight; //增加的width
double yTop = (y/yHeight) *yNarrowAddWidth;
_yMaxTmp =_yMaxTmp+yTop*yRate;
double yBottom =yNarrowAddWidth- (y/yHeight) *yNarrowAddWidth;
_yMinTmp =_yMinTmp-yBottom*yRate;
qDebug()<<"缩小后 xMin:"<<_xMinTmp<<" 缩小后 xMax:"<<_xMaxTmp;
_isScale=true;
}
void EVChartView::getSeeAreaLine()
{
//获取可视区域
_vSeeAreaLine.clear();
QVector<QLine> tmp ;
double chartWmin=m_leftDisplayWidth;
double chartWmax=_width-m_rightDisplayWidth;
double chartHmin=m_headerHeight;
double chartHmax=_height-m_bottomHeight;
double xRate =(double)(chartWmax-chartWmin)/(_xMaxTmp-_xMinTmp);
//y轴长度
int chartHeightLength = chartHmax-chartHmin;
double yRate =((double)chartHeightLength)/(_yMaxTmp-_yMinTmp);
//选择时间后 读取数据库后传入
QStringList list= getCurrentFrame("");
if(list.size()>0){
int index =_xMinTmp;
int max =_xMaxTmp;
int tmp11 =0;
for( ; index<max;index++){
if(index>=list.size()){
break;
}
if(index<=0){
//x 将值算好
tmp11++;
continue;
}
tmp11++;
double xStartP=0.f,yStartP=0.f;
double xEndP=0.f,yEndP=0.f;
xStartP=(double)chartWmin+(xRate*((double)tmp11-1/*-_xMinTmp*/));
double ystart= list[index-1].toDouble();
//y匹配坐标系
yStartP=m_headerHeight+yRate*(_yMaxTmp- ystart);
xEndP =(double)chartWmin+xRate*((double)tmp11/*-_xMinTmp*/);
yEndP =(double)m_headerHeight+yRate*(_yMaxTmp-list[index].toDouble());
QLine line =QLine(xStartP,yStartP,xEndP,yEndP);
tmp.append(line);
_vSeeAreaLine.append(line);
}
}
}
double EVChartView::initDouble(double &bRate)
{
QString num=QString::number(bRate,'f',8);
//取到不为0的开始 补齐为5 假如为0.0004 则补齐为 0.0005 每次加
return 0.0;
}
double EVChartView::getYScaleValue()
{
_yScaleCount++;
if(_yScaleCount<=0) return 1;
return _yScale;
}
double EVChartView::getXScaleValue()
{
_xScaleCount++;
if(_xScaleCount<=0) return 1;
return _xScale;
}
void EVChartView::setFont()
{
QFont font;
font.setPointSize(10);
font.setFamily("Microsoft YaHei");
font.setLetterSpacing(QFont::AbsoluteSpacing,0);
_painter->setFont(font);
_painter->setRenderHint(QPainter::Antialiasing);
}
QString EVChartView::removeZero(double data)
{
QString label;
QRegExp reg;
reg.setPattern("(\\.){0,1}0+$");
QString dds = QString("%1").arg(data, 0, 'f', 2).replace(reg, "");
label=dds;
return "";
}
bool EVChartView::isXaxisInt()
{
double xLen = ((double)_xMaxTmp- (double)_xMinTmp)/m_hTickCount;
if(isInt(xLen)){
return true;
}else{
//偏移 正数 如果大于0.5 向前取整 小于0.5向后取整
int data =xLen;
double leftData =xLen-data;
if(leftData>0.5){
xLen =data+1;
}else{
xLen =data;
}
}
//将 轴计算出来
_xMaxTmp =_xMinTmp+xLen*m_hTickCount;
return true;
}
bool EVChartView::isInt(const double &dData)
{
int nData = (int)dData;
if(nData==dData){
return true;
}else{
return false;
}
}
QStringList EVChartView::stepZoom(double &min, double &max)
{
//最小步径
QStringList list;
list<<"0"<<"1"<<"2"<<"4"<<"5"<<"6"<<"7"<<"8";
if(min==0 &&max ==0) return list;
list.clear();
double dlen = max-min;
int nlen =0;
bool isSacleData =false;
if(dlen<=100){
nlen = dlen*10000;
isSacleData =true;
}else{
nlen =dlen;
}
int step=((nlen))%(5*_yTickCountTmp);
if(step==0){
step =((nlen))/(5*_yTickCountTmp);
for(int index=0 ;index<_yTickCountTmp+1;index++){
if(isSacleData){
list<<QString::number(min+(double)(step)*index*5/10000,'f',3);
}else{
list<<QString::number(min+(double)(step)*index*5,'f',3);
}
}
return list;
}
step=((nlen))%(2*_yTickCountTmp);
if(step==0){
step =((nlen))/(2*_yTickCountTmp);
for(int index=0 ;index<_yTickCountTmp+1;index++){
if(isSacleData){
list<<QString::number(min+(double)(step)*index*2/10000,'f',3);
}else{
list<<QString::number(min+(double)(step)*index*2,'f',3);
}
}
return list;
}
step=((nlen))%(_yTickCountTmp);
if(step==0){
step =((nlen))/(_yTickCountTmp);
for(int index=0 ;index<_yTickCountTmp+1;index++){
if(isSacleData){
list<<QString::number(min+(double)(step)*index/10000,'f',3);
}else{
list<<QString::number(min+(double)(step)*index,'f',3);
}
}
return list;
}
//未返回 补长度 将长度补为5 2 1中最短的
int step5=((nlen))%(5*_yTickCountTmp);
int step2 =((nlen))%(2*_yTickCountTmp);
int step1 =((nlen))%(1*_yTickCountTmp);
int value =0;
//判断1 2 5 并补齐
if(step5>step2){
if(step5>step1){
value =step5;
}else{
value =step1;
}
}else{
if(step2>step1){
value =step2;
}else{
value =step1;
}
}
if(value==step5){
//补回去补齐
double maxTmp =0.f;
double minTmp =0.f;
if(isSacleData){
maxTmp = max+ ((double)((5*_yTickCountTmp)) -step5)/10000/2;
minTmp = min- ((double)((5*_yTickCountTmp) -step5))/10000/2;
nlen = (maxTmp-minTmp)*10000;
}else{
maxTmp = max+ ((double)((_yTickCountTmp)) -step5)/2;
minTmp = min- ((double)((_yTickCountTmp) -step5))/2;
nlen = (maxTmp-minTmp);
}
step=nlen/(5*_yTickCountTmp);
for(int index=0 ;index<(_yTickCountTmp+1);index++){
if(isSacleData){
list<<QString::number(minTmp+(double)(step)*index/10000,'f',3);
}else{
list<<QString::number(minTmp+(double)(step)*index,'f',3);
}
}
min =minTmp;
max =maxTmp;
return list;
}else if(value==step2){
double maxTmp =0.f;
double minTmp =0.f;
if(isSacleData){
maxTmp = max+ ((double)((_yTickCountTmp)) -step2)/10000/2;
minTmp = min- ((double)((_yTickCountTmp) -step2))/10000/2;
nlen = (maxTmp-minTmp)*10000;
}else{
maxTmp = max+ ((double)((_yTickCountTmp)) -step2)/2;
minTmp = min- ((double)((_yTickCountTmp) -step2))/2;
nlen = (maxTmp-minTmp);
}
step=nlen/(2*_yTickCountTmp);
for(int index=0 ;index<(_yTickCountTmp+1);index++){
if(isSacleData){
list<<QString::number(minTmp+(double)(step)*index/10000,'f',3);
}else{
list<<QString::number(minTmp+(double)(step)*index,'f',3);
}
}
min =minTmp;
max =maxTmp;
return list;
}else{
double maxTmp =0.f;
double minTmp =0.f;
if(isSacleData){
maxTmp = max+ ((double)((_yTickCountTmp)) -step1)/10000/2;
minTmp = min- ((double)((_yTickCountTmp) -step1))/10000/2;
nlen = (maxTmp-minTmp)*10000;
}else{
maxTmp = max+ ((double)((_yTickCountTmp)) -step1)/2;
minTmp = min- ((double)((_yTickCountTmp) -step1))/2;
nlen = (maxTmp-minTmp);
}
step=nlen/(_yTickCountTmp);
for(int index=0 ;index<(_yTickCountTmp+1);index++){
if(isSacleData){
list<<QString::number(minTmp+(double)(step)*index/10000,'f',3);
}else{
list<<QString::number(minTmp+(double)(step)*index,'f',3);
}
}
min =minTmp;
max =maxTmp;
return list;
}
}
#ifndef EVChartView_H
#define EVChartView_H
#include <QObject>
#include <QQuickPaintedItem>
#include "PropertyHelper.h"
#include <QPainter>
#include <QList>
#include <QMutex>
class EVChartView : public QQuickPaintedItem
{
Q_OBJECT
public:
EVChartView(QQuickItem *parent = 0);
~EVChartView();
AUTO_PROPERTY(int,vTickCount,5)
AUTO_PROPERTY(int,hTickCount,5)
AUTO_PROPERTY(QString,headerTxt,"")
AUTO_PROPERTY(QString,headerTxtColor,"")
AUTO_PROPERTY(int,headerHeight,20)
AUTO_PROPERTY(int,leftDisplayWidth,0)
AUTO_PROPERTY(int,rightDisplayWidth,0)
AUTO_PROPERTY(int,bottomHeight,0)
AUTO_PROPERTY(int,xMax,24000)
AUTO_PROPERTY(int,xMin,-24000)
AUTO_PROPERTY(int,yMax,10)
AUTO_PROPERTY(int,yMin,0)
AUTO_PROPERTY(QString,leftLabel,"")
public:
Q_INVOKABLE void setLine(QStringList list);
Q_INVOKABLE void clearLine();
Q_INVOKABLE void startTest(); //测试数据 支持百万级瞬绘
protected:
void paint(QPainter *painter) override;
protected:
//--------------鼠标事件-----------------------------
//鼠标进入事件
virtual void hoverEnterEvent(QHoverEvent *event) override;
//鼠标离开事件
virtual void hoverLeaveEvent(QHoverEvent *event) override;
//鼠标移动事件
virtual void hoverMoveEvent(QHoverEvent *event) override;
//鼠标滚轮事件
virtual void wheelEvent(QWheelEvent *event) override;
private:
//----------------------chartView paint操作----------------------------------
void drawHeader(); //画Header
void drawFrame(); //画外边框
void drawHorizontalLine(); //画水平线
void drawLeftTickLabel(); //画垂直线
//void drawLeftTitle(); //画垂直的单位
void drawBottomTitle(); //画底部单位
void drawLeftLabel(); //
private:
//------------------- 画线 放大 缩小 操作---------------------------------------------
void drawVlines(); //画线 Qt自动将重合线去重
QStringList getCurrentFrame(const QString & strframeValue); //获取当前可画线区域
void pointScale(const QPoint &point); //放大
void pointNarrow(const QPoint &point); //缩小
void getSeeAreaLine(); //生成折线
double initDouble(double &bRate); //将第一次比例初始化
double getYScaleValue(); //获取y放大倍数
double getXScaleValue(); //获取x放大倍数
void setFont();
//一格小于100操作
private:
QString removeZero(double data);
bool isXaxisInt();
bool isInt(const double &dData);
QStringList stepZoom(double &min,double &max);
private:
QPainter* _painter;
double _width=0.f;
double _height =0.f;
QVector<QLine> _vLine;
QRectF _chartFrame;
QPoint _currentPos;
double _xSpace=0; //基本x比例
double _ySpace=0; //基本y比例
double _xCurrentSpace=0; //当前x比例
double _yCurrentSpace=0; //当前y比例
double _xMinTmp=0;
double _xMaxTmp=0;
double _yMinTmp=0;
double _yMaxTmp=0;
int _scaleCount =0;
int _scaleXCount =0;
QVector<QLine> _vSeeAreaLine;
double _xScale =2; //x放大倍数
double _yScale =2; //y放大倍数
int _xScaleCount =0; //x放大次数
int _yScaleCount =0; //y放大次数
bool _isScale = false;
int _yTickCountTmp =0;
int _xTickCountTmp =0;
};
#endif // EVChartView_H
#pragma once
#include <QObject>
#include <QtGlobal>
template <typename T>
struct Compare;
template <typename T>
struct Compare
{
static bool isEqual(const T& t1, const T& t2)
{
return t1 == t2;
}
};
template <>
struct Compare<float>
{
static bool isEqual(float f1, float f2)
{
return qFuzzyCompare(f1, f2);
}
};
template <>
struct Compare<double>
{
static bool isEqual(double d1, double d2)
{
return qFuzzyCompare(d1, d2);
}
};
// member variant
#define PROP_MEM(T, NAME, InitValue) T m_##NAME = InitValue;
#define MEM_GET(T, NAME) \
const T& NAME() const \
{ \
return m_##NAME; \
}
#define MEM_SET(T, NAME) \
void set_##NAME(const T& value) \
{ \
m_##NAME = value; \
}
// get method
#define PROP_GET(T, NAME) \
const T& NAME() const \
{ \
return m_##NAME; \
}
// change signal
#define PROP_CHANGE(T, NAME) Q_SIGNAL void NAME##Changed(const T& value);
// set method
#define PROP_SET(T, NAME) \
void set_##NAME(const T& value) \
{ \
if (Compare<T>::isEqual(m_##NAME, value)) \
return; \
m_##NAME = value; \
emit NAME##Changed(value); \
}
// ReadOnly property
#define READONLY_PROPERTY(T, NAME, InitValue) \
private: \
Q_PROPERTY(T NAME READ NAME CONSTANT) \
public: \
PROP_GET(T, NAME) \
private: \
PROP_MEM(T, NAME, InitValue)
// Readable property
#define READ_PROPERTY(T, NAME, InitValue) \
private: \
Q_PROPERTY(T NAME READ NAME NOTIFY NAME##Changed) \
public: \
PROP_GET(T, NAME) \
PROP_SET(T, NAME) \
PROP_CHANGE(T, NAME) \
private: \
PROP_MEM(T, NAME, InitValue)
// Read Write member
#define AUTO_MEM(T, NAME, InitValue) \
public: \
MEM_GET(T, NAME) \
MEM_SET(T, NAME) \
private: \
PROP_MEM(T, NAME, InitValue)
// Read Write property
#define AUTO_PROPERTY(T, NAME, InitValue) \
private: \
Q_PROPERTY(T NAME READ NAME WRITE set_##NAME NOTIFY NAME##Changed) \
public: \
PROP_GET(T, NAME) \
Q_SLOT PROP_SET(T, NAME) PROP_CHANGE(T, NAME) private : PROP_MEM(T, NAME, InitValue)
/**
* Example:
*
class AppInfo : public QObject
{
Q_OBJECT
//第三个参数为初始化
AUTO_PROPERTY(QString, appName, "")
AUTO_PROPERTY(QString, descript, "")
AUTO_PROPERTY(QString, compilerVendor, "")
AUTO_PROPERTY(bool, splashShow, false)
AUTO_PROPERTY(float, scale, 1.0f)
AUTO_PROPERTY(double, ratio, 14.0 / 9.0)
AUTO_PROPERTY(QStringList, customs, {})
public:
explicit AppInfo(QObject *parent = nullptr);
virtual ~AppInfo() override;
public:
};
*/
#include "Dashboard.h"
#include <qmath.h>
const int radius = 180; //半径
const int maxv = 300; //最大刻度值
const int minv = 0; //最小刻度值
const int longstep = 10; //长刻度步长
const int shortstep = maxv/longstep; //短刻度步长
const double startDraw = -135.0; //绘制起始角度
const double stopDraw = 270.0; //绘制结束角度
Dashboard::Dashboard(QQuickItem *parent):
QQuickPaintedItem(parent)
{
Values = 0;
}
Dashboard::~Dashboard()
{
}
void Dashboard::setValues(unsigned int &iValues)
{
Values = iValues;
update();
}
void Dashboard::paint(QPainter *painter)
{
painter->setRenderHint(QPainter::Antialiasing);
QPoint center(width()/2,height()/2);
painter->save();
//绘制背景
painter->translate(center);
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(142,142,142)); // 设置背景颜色
int bkRadius = radius+3;
painter->drawEllipse(QPoint(),bkRadius ,bkRadius);
//绘制刻度线
painter->rotate(startDraw);
for (int i = 0; i <=shortstep; i ++) {
painter->setPen(i<shortstep*0.8?QColor(32,243,32):QColor(243,32,32));
if(i%(shortstep/longstep) != 0)
{
QPoint p1(0,-(radius - 8));
QPoint p2(0,-radius);
painter->drawLine(p1,p2);
}else{
QPoint p1(0,-(radius - 14));
QPoint p2(0,-radius);
painter->drawLine(p1,p2);
}
painter->rotate(stopDraw/shortstep);
}
painter->restore();
QFontMetrics fm = painter->fontMetrics();
int tx = center.x();
int ty =int(center.y()+(radius/1.4));
//title
QString title = "仪表盘";
QSize tsz = fm.size(0,title);
QRect trect(QPoint(tx-tsz.width()/2,ty-tsz.height()/2),tsz);
painter->setPen(QColor(127,127,127));
painter->setBrush(QColor(173,163,163));
painter->drawRoundedRect(trect.adjusted(-6,-4,6,4),3,3);
painter->setPen(QColor(243,243,243));
painter->setBrush(Qt::NoBrush);
painter->drawText(trect,title);
painter->setPen(QColor(243,243,243));
int hand = radius -21;
for (int i = 0;i<= longstep ;i++) {
qreal angle = qDegreesToRadians(startDraw+i*(stopDraw/longstep));
QString etext = QString::number(minv+i*(maxv - minv)/longstep);
QPointF dirvec(qSin(angle),-qCos(angle));
QPointF ecenter(center.x()+hand*dirvec.x(),center.y()+hand*dirvec.y());
QSize esz = fm.size(0,etext);
QRectF erect(QPointF(ecenter.x()-esz.width()/2,ecenter.y()-esz.height()/2),esz);
painter->drawText(erect,etext);
}
//仪表盘指针绘制
painter->save();
QPoint triangle[]={
{-5,0},
{0,30-radius},
{5,0}
};
qreal degree = startDraw + stopDraw*(Values - minv)/(maxv - minv);
painter->translate(center);
painter->rotate(degree);
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::red);
painter->drawPolygon(triangle,3);
painter->setPen(QPen(QColor(214,0,0),2));
painter->drawEllipse(QPoint(),7,7);
painter->restore();
}
#ifndef DASHBOARD_H
#define DASHBOARD_H
#include <QQuickPaintedItem>
#include <QQuickItem>
#include <QPainter>
class Dashboard : public QQuickPaintedItem
{
Q_OBJECT
public:
Dashboard(QQuickItem *parent = nullptr);
~Dashboard();
public:
void setValues(unsigned int& iValues);
protected:
void paint(QPainter *painter);
private:
qreal Values;
};
#endif // DASHBOARD_H
<RCC>
<qresource prefix="/">
<file>qml/main.qml</file>
<file>qml/ModelComponent.qml</file>
<file>qml/model-qml/graphical/GraphicalControl.qml</file>
</qresource>
</RCC>
import QtQuick 2.0
import "./model-qml/graphical"
Rectangle {
width: parent.width
height: parent.height
color: "#999999"
property var modeDataText: ["图形","图片"]
signal listViewIndexChange(int index)
onListViewIndexChange: {
modelLoader.source = ""
if(index == 0)
{
modelLoader.source ="qrc:/qml/model-qml/graphical/GraphicalControl.qml"
}
else if(index == 1)
{
}
}
Loader{
id:modelLoader
width: parent.width
height:parent.height
source:"qrc:/qml/model-qml/graphical/GraphicalControl.qml"
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
Window {
visible: true
width: 800
height:600
title: qsTr("样例")
ListView{
id:listView
width: 150
x:0
y:0
height: parent.height
model: modelComponent.modeDataText
clip: true
ScrollBar.vertical: ScrollBar {active: true}
delegate: Rectangle{
width: parent.width
height: 30
color:listView.currentIndex == index?"#003891": "#999999"
Text {
anchors.centerIn: parent
text: modelData
color: "white"
font.pointSize: 12
font.family: "微软雅黑"
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
listView.currentIndex = index
modelComponent.listViewIndexChange(index)
}
}
}
}
ModelComponent{
id:modelComponent
width: parent.width-listView.width
height: parent.height
anchors.left: listView.right
color: "white"
border.color: "#666666"
}
}
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Zs.model 1.0
Rectangle{
width: parent.width
height: parent.height
property var modeDataText: ["仪表盘","折线图"]
Column{
anchors.fill: parent
spacing: 10
Rectangle{
width: parent.width
height: 30
ListView{
id:listView
width: parent.width
height: parent.height
x:0
y:0
model:modeDataText
clip: true
orientation:ListView.Horizontal
// ScrollBar.horizontal: ScrollBar {active: true}
delegate: Rectangle{
width: 60
height: 30
color:listView.currentIndex == index?"#003891": "#999999"
Text {
anchors.centerIn: parent
text: modelData
color: "white"
font.pointSize: 10
font.family: "微软雅黑"
}
MouseArea{
anchors.fill: parent
hoverEnabled: true
onClicked: {
listView.currentIndex = index
if(index == 1)
{
sddddd.startTest()
}
}
}
}
}
}
StackLayout{
width: parent.width
height: parent.height-100
currentIndex:listView.currentIndex
Dashboard{
width:parent.width
height: parent.height
}
EVChartView{
id:sddddd
width:parent.width
height: parent.height-200
vTickCount: 8
hTickCount:5
headerTxt: "折线图"
headerTxtColor: "red"
leftDisplayWidth: (120)
rightDisplayWidth: (60)
bottomHeight: (30)
headerHeight: (30)
yMin: -5
yMax: 5
xMin: 0
xMax: 24000
leftLabel:"Voltage.V"
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册