我使用Qt Scene Graph(Ubuntu 16.04上的Qt 5.6)创建了一个应用程序。它有大约12个QSGNode实例,并且每30ms调用一次更新。
我没有更新其中一个的任何问题,但是当我为所有人调用更新时,cpu和ram的使用率开始增加。几个小时后,CPU使用率将接近100%。 (在正常情况下,cpu的使用量应该在3-4左右)。
这是最小版本(对于长代码很抱歉,这是产生此错误的最简单版本):
main.cpp
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "gui/diagramgraph.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QQuickView>
#include <QTimer>
#include "gui/diagramgraph.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qmlRegisterType<DiagramGraph>("DiagramGraph", 1, 0, "DiagramGraph");
QTimer *updateTimer = new QTimer(this);
for(int i = 1; i <= 12; i++){
QQuickView *view = new QQuickView();
view->setSource(QUrl("qrc:/ui/diagram.qml"));
view->setClearBeforeRendering(true);
QObject *object = view->rootObject();
DiagramGraph* graph = object->findChild<DiagramGraph *>("diagram");
QObject::connect(updateTimer, SIGNAL(timeout()), graph, SLOT(update()));
QWidget *container = QWidget::createWindowContainer(view, this);
ui->vetical->addWidget(container);
}
updateTimer->setTimerType(Qt::PreciseTimer);
updateTimer->start(30);
}
MainWindow::~MainWindow()
{
delete ui;
}
GUI / diagramgraph.h
#ifndef DIAGRAMGRAPH_H
#define DIAGRAMGRAPH_H
#include <QQuickItem>
class DiagramGraph : public QQuickItem
{
Q_OBJECT
public:
DiagramGraph();
void init();
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
};
#endif // DIAGRAMGRAPH_H
GUI / diagramgraph.cpp
#include "samples.h"
#include "diagramgraph.h"
class DiagramGraphNode : public QSGNode
{
public:
Samples * samples;
};
DiagramGraph::DiagramGraph()
{
setFlag(ItemHasContents, true);
}
QSGNode * DiagramGraph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *){
DiagramGraphNode *n= static_cast<DiagramGraphNode *>(oldNode);
QRectF rect = boundingRect();
if (rect.isEmpty()) {
delete n;
return 0;
}
if (!n) {
n = new DiagramGraphNode();
n->samples = new Samples();
n->appendChildNode(n->samples);
}
n->samples->updateGeometry();
return n;
}
void DiagramGraph::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry){
update();
QQuickItem::geometryChanged(newGeometry, oldGeometry);
}
GUI / samples.h
#ifndef SAMPLES_H
#define SAMPLES_H
#include <QSGGeometryNode>
class Samples : public QSGGeometryNode
{
public:
Samples();
void updateGeometry();
private:
QSGGeometry _geometry;
};
#endif // SAMPLES_H
GUI / samples.cpp
#include "samples.h"
#include <QtGui/QColor>
#include <QtQuick/QSGSimpleMaterial>
struct LineMaterial
{
QColor color;
};
class LineShader : public QSGSimpleMaterialShader<LineMaterial>
{
QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial)
public:
LineShader() {
setShaderSourceFile(QOpenGLShader::Vertex, ":/shaders/shaders/samples.vsh");
setShaderSourceFile(QOpenGLShader::Fragment, ":/shaders/shaders/samples.fsh");
}
QList<QByteArray> attributes() const { return QList<QByteArray>() << "y" << "t"; }
void updateState(const LineMaterial *m, const LineMaterial *) {
program()->setUniformValue(id_color, m->color);
}
void resolveUniforms() {
id_color = program()->uniformLocation("color");
}
private:
int id_color;
};
struct Vertex {
float y;
float t;
inline void set(float yy, float tt) { y = yy; t = tt; }
};
static const QSGGeometry::AttributeSet &attributes()
{
static QSGGeometry::Attribute attr[] = {
QSGGeometry::Attribute::create(0, 1, GL_FLOAT, true),
QSGGeometry::Attribute::create(1, 1, GL_FLOAT),
};
static QSGGeometry::AttributeSet set = { 2, 2 * sizeof(float), attr };
return set;
}
Samples::Samples()
: _geometry(attributes(), 0){
setGeometry(&_geometry);
_geometry.setLineWidth(3);
_geometry.setDrawingMode(GL_LINES);
QSGSimpleMaterial<LineMaterial> *m = LineShader::createMaterial();
m->state()->color = QColor("red");
m->setFlag(QSGMaterial::Blending);
setMaterial(m);
setFlag(OwnsMaterial);
}
void Samples::updateGeometry()
{
_geometry.allocate(20);
Vertex *v = (Vertex *) _geometry.vertexData();
for (uint i=0; i < 20; i++){
v[i].set(.5, i);
}
}
mainwindow.ui
just a QVBoxLayout
diagram.qml
import QtQuick 2.0
import QtQuick.Controls 1.4
import DiagramGraph 1.0
Item{
id: diagram_main
DiagramGraph{
id: diagram_graph
objectName: "diagram"
anchors.left: diagram_main.left
height: 100
}
}
着色器/ samples.fsh
uniform lowp vec4 color;
uniform lowp float qt_Opacity;
void main(void)
{
gl_FragColor = color * qt_Opacity;
}
着色器/ samples.vsh
attribute highp float y;
attribute highp float t;
uniform highp mat4 qt_Matrix;
void main(void)
{
gl_Position = qt_Matrix * vec4(t, y * 100.f, 0.f, 1.f);
}