最近在做一个关于坐标的界面,

花了两天用qml画出来了,这里贴出来分享一下;

c++类OrdinateItem;

ordinateItem.h文件

#ifndef ORDINATEITEMS_H
#define ORDINATEITEMS_H

#include <QQuickItem>

namespace UtAbCapb {

class OrdinateItem : public QQuickItem//这里必须继承QQuickItem,因为要用到它的很多属性
{
Q_OBJECT
Q_PROPERTY(int scaleViewPostion READ scaleViewPostion WRITE setScaleViewPostion NOTIFY scaleViewPostionChanged)
Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged)
Q_PROPERTY(QString lineColor READ lineColor WRITE setLineColor NOTIFY lineColorChanged)
Q_PROPERTY(int rulerTotal READ rulerTotal WRITE setRulerTotal NOTIFY rulerTotalChanged)

enum scaleVP{
RightVP=0,
LeftVP
};
public:
OrdinateItem();//构造

private:
void init();//初始化
public:
int scaleViewPostion(); // 刻度显示位置(0:默认左边,1:右边)
void setScaleViewPostion(int vp); //设置刻度显示位置
int lineWidth(); // 画线线宽(默认3)
void setLineWidth(int width); //设置线宽
QString lineColor(); // 画线颜色
void setLineColor(QString color); //设置画线颜色
int rulerTotal(); // 总刻度数(默认4)
void setRulerTotal(int count); //设置刻度数

QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);//更新节点

signals:
void scaleViewPostionChanged(); //刻度显示位置变化信号
void lineWidthChanged(); //线宽变化
void lineColorChanged(); //线颜色变化
void rulerTotalChanged(); //刻度总是变化
void rulerUnitChanged(); //刻度初始位置信号
public slots:

private:
int m_scale_vp; // 刻度显示位置
int m_line_width; // 线宽
QString m_line_color; // 线颜色
int m_ruler_count; // 刻度大小
};

}
#endif // ORDINATEITEMS_H

ordinateItem.cpp文件


#include "ordinateitem.h"
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
#include <QDebug>

namespace UtAbCapb {

OrdinateItem::OrdinateItem()
{
setFlag(ItemHasContents, true);//设置标识
this->init();
}

void OrdinateItem::init()//初始化刻度,线宽,颜色等
{
m_scale_vp = LeftVP;
m_line_width = 1;
m_line_color = "#C5AD63";
m_ruler_count = 35;//纵坐标刻度35
}

int OrdinateItem::scaleViewPostion()
{
return m_scale_vp;
}

void OrdinateItem::setScaleViewPostion(int vp)
{
m_scale_vp = vp;
}

int OrdinateItem::lineWidth()
{
return m_line_width;
}

void OrdinateItem::setLineWidth(int width)
{
m_line_width = width;
}

QString OrdinateItem::lineColor()
{
return m_line_color;
}

void OrdinateItem::setLineColor(QString color)
{
m_line_color = color;
}

int OrdinateItem::rulerTotal()
{
return m_ruler_count;
}

void OrdinateItem::setRulerTotal(int count)
{
if(count>=10 && count<120){
m_ruler_count = count;
update();
}
}

QSGNode *OrdinateItem::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
float max_x = (width()>30)? 20 : width();//定义获取宽度,这里获取的是qml中设定的宽度
float max_y = height();//获取高度因为继承了QQuickItem
float rulerUnit = (max_y-10)/m_ruler_count;//卡尺比例
float scal_h = max_x;//毫米刻度,
float scal_m = max_x*0.8;//分米刻度
float scal_l = max_x*0.5;//厘米刻度
int totalCount = m_ruler_count*2 + 4;//刻度总数

QSGGeometryNode *node = 0;//定义node,用于场景图中的所有渲染内容
node = static_cast<QSGGeometryNode *>(oldNode);
QSGGeometry *geometry;//定义geometry,为图形提供低级存储
QSGFlatColorMaterial *material;//定义material,提供了一种在场景图中绘制纯色几何图形的方法
if(!node) {
node = new QSGGeometryNode;
geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), totalCount);//默认2d绘图。创建一个没有几何和材质的新的几何节点
geometry->setDrawingMode(GL_LINES);//绘图模式,GL画线
geometry->setLineWidth(m_line_width);//设置线宽
material = new QSGFlatColorMaterial;//实例
material->setColor(QColor(m_line_color));//设置颜色
node->setGeometry(geometry);//将geometry添加到node
node->setFlag(QSGNode::OwnsGeometry);//
node->setMaterial(material);//将此几何节点的材质设置为material
} else {
geometry = node->geometry();
material = static_cast<QSGFlatColorMaterial *>(node->material());
geometry->allocate(totalCount);
}
//定义vertices,获取的是geometry,2D的顶点数据指针
QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
int max = (m_scale_vp == LeftVP)? max_x : 0;//显示的位置
vertices[0].set(max, 0);//画直线从0开始画到max_y
vertices[1].set(max, max_y);//根据的是屏幕分辨率高度
float x0=0;
float y0=max_y;
float x;
float y;
int cout =1;
for(int i=0;i<=m_ruler_count;i++){
int itype = (i%5==0 && i%10==0)? 0 :((i%5==0 && i%10!=0)? 1 : 2); //0:max,1:mid,2:min
switch (itype) {
case 0:
x0 = 0;
x = scal_h;
y = y0;
break;
case 1:
x0 = (m_scale_vp == LeftVP)? scal_h*0.2 : 0;
x = (m_scale_vp == LeftVP)? scal_h : scal_m;
y = y0;
break;
case 2:
x0 = (m_scale_vp == LeftVP)? scal_l : 0;
x = (m_scale_vp == LeftVP)? scal_h : scal_l;
y = y0;
break;
default:
break;
}
vertices[++cout].set(x0, y0);//画线起始点
vertices[++cout].set(x, y);//终止点
y0 = y0 - rulerUnit;
}
node->markDirty(QSGNode::DirtyGeometry);
return node;
}
}

在主函数main中:

qmlRegisterType<OrdinateItem>("OrdinateItem.com", 1, 0, "OrdinateItem");//注册到qml中

在qml中引用:

import OrdinateItem.com 1.0

 

然后可以用了;

OrdinateItem{ id: ordId; width: 20; height: parent.height*0.4; rulerTotal: 35; anchors.bottom: horId.top;
//scaleViewPostion: 1
MouseArea{ anchors.fill: parent;
property point clickPos: "0,0"
onPressed: {
clickPos = Qt.point(mouse.x,mouse.y);
}
onPositionChanged: {
//鼠标偏移量
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
coordId.x = coordId.x+delta.x;
coordId.y = coordId.y+delta.y;
}
}
}