在寻找如何使用QSGTransformNode的过程中发现如下图片,于是尝试一下
效果
关键部分
基本图像都是由这些QSGNode构成的,Node之间存在父与子的关系,改变了父就会改变所有子节点。例如我增加了Transform效果,做一个平移或者旋转,需要跟着运动的就是它的子节点。
下面是部分代码,在官方例子基础上增加的。这里关键是使用了quick item类的鼠标点击事件。
Graph::Graph()
: m_samplesChanged(false)
, m_geometryChanged(false)
,m_matrixChanged(false)
{
setAcceptedMouseButtons(Qt::LeftButton
| Qt::RightButton
| Qt::MiddleButton);
setFlag(ItemHasContents, true);
}
void Graph::mousePressEvent(QMouseEvent* event)
{
event->accept();
mouse_press = event->localPos();
}
void Graph::mouseMoveEvent(QMouseEvent* event)
{
event->accept();
QPointF pos = event->localPos();
//QMatrix4x4的平移方法
matrix.translate(pos.x() - mouse_press.x(), pos.y() - mouse_press.y());
//也可以使用他的别的方法,比如旋转 matrix.rotate(30,0,1,0) // 绕着y轴旋转30度
m_matrixChanged=true;
mouse_press = event->localPos();
update();
}
void Graph::mouseReleaseEvent(QMouseEvent* event)
{
event->accept();
update();
}
这里是把原本继承的GsgNode改为QSGTransformNode,这样我使用GraphNode的QSGTransformNode::setMatrix方法就能进行整个图形的变换。
class GraphNode : public QSGTransformNode
{
public:
NoisyNode *background;
GridNode *grid;
LineNode *line;
LineNode *shadow;
};
全部代码
#ifndef GRAPH_H
#define GRAPH_H
#include <QMatrix4x4>
#include <QQuickItem>
class Graph : public QQuickItem
{
Q_OBJECT
QML_ELEMENT
public:
Graph();
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry);
public slots:
void appendSample(qreal value);
void removeFirstSample();
private:
QList<qreal> m_samples;
QMatrix4x4 matrix;
QPointF mouse_press;
bool m_samplesChanged;
bool m_geometryChanged;
bool m_matrixChanged;
};
#endif // GRAPH_H
#include "graph.h"
#include "noisynode.h"
#include "gridnode.h"
#include "linenode.h"
Graph::Graph()
: m_samplesChanged(false)
, m_geometryChanged(false)
,m_matrixChanged(false)
{
setAcceptedMouseButtons(Qt::LeftButton
| Qt::RightButton
| Qt::MiddleButton);
setFlag(ItemHasContents, true);
}
void Graph::appendSample(qreal value)
{
m_samples << value;
m_samplesChanged = true;
update();
}
void Graph::removeFirstSample()
{
m_samples.removeFirst();
m_samplesChanged = true;
update();
}
void Graph::mousePressEvent(QMouseEvent* event)
{
event->accept();
mouse_press = event->localPos();
}
void Graph::mouseMoveEvent(QMouseEvent* event)
{
event->accept();
QPointF pos = event->localPos();
matrix.translate(pos.x() - mouse_press.x(), pos.y() - mouse_press.y());
m_matrixChanged=true;
mouse_press = event->localPos();
update();
}
void Graph::mouseReleaseEvent(QMouseEvent* event)
{
event->accept();
update();
}
void Graph::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
{
m_geometryChanged = true;
update();
QQuickItem::geometryChange(newGeometry, oldGeometry);
}
class GraphNode : public QSGTransformNode
{
public:
NoisyNode *background;
GridNode *grid;
LineNode *line;
LineNode *shadow;
};
QSGNode *Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
GraphNode *n= static_cast<GraphNode *>(oldNode);
QRectF rect = boundingRect();
if (rect.isEmpty()) {
delete n;
return nullptr;
}
if (!n) {
n = new GraphNode();
n->background = new NoisyNode(window());
n->grid = new GridNode();
n->line = new LineNode(10, 0.5, QColor("steelblue"));
n->shadow = new LineNode(20, 0.2f, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4));
matrix=n->matrix();
n->appendChildNode(n->background);
n->appendChildNode(n->grid);
n->appendChildNode(n->shadow);
n->appendChildNode(n->line);
}
if(m_matrixChanged )
{
n->setMatrix(matrix);
}
if (m_geometryChanged) {
n->background->setRect(rect);
n->grid->setRect(rect);
}
if (m_geometryChanged || m_samplesChanged) {
n->line->updateGeometry(rect, m_samples);
// We don't need to calculate the geometry twice, so just steal it from the other one...
n->shadow->setGeometry(n->line->geometry());
}
m_geometryChanged = false;
m_samplesChanged = false;
m_matrixChanged = false;
return n;
}