我想制作带有条形图的3D图表,条形颜色取决于其大小。两者Qt bar and scatter graph types都接近我要寻找的。我最终基于Q3DScatter
创建了一个图表,并添加了QCustom3DItem
来绘制条形图,因此我可以为每个项目设置一个网格项和颜色。图表的每个位置都有一个项目。假设它是100x100的图表,这意味着有10000条(自定义项目)。
我想每秒多次重绘整个图表。通过重画,我的意思是每个项目都会改变其大小和颜色。要设置项目大小,我呼叫setScalling()。因为缩放是通过保持项目的中心位置(并且我想保持条形基准位置)来进行的,所以在缩放之后我必须调用setPosition。并设置颜色,我叫setTextureImage()。因此,每秒多次,调用类似于以下get的代码:
for (int col = 0; col < 100; col++)
for (int row = 0; row < 100; row++) {
items[row*COLS+col]->setScalling(scale);
items[row*COLS+col]->setPosition(position);
items[row*COLS+col]->setTextureImage(image);
}
这几乎可以预期。问题不够快。关于如何使其更快的任何提示?
我试图将自定义项目移动到另一个线程。
为了将QCustom3DItem
的处理(即缩放)从主(gui)线程中移出,我这样做:
project.pro
QT += core gui widgets datavisualization
TEMPLATE = app
CONFIG += c++11
SOURCES += main.cpp mainwindow.cpp graphdata.cpp
HEADERS += mainwindow.h graphdata.h
RESOURCES += mesh.qrc
CONFIG(debug, debug|release) {
DESTDIR = debug
} else {
DESTDIR = release
}
OBJECTS_DIR = $$DESTDIR/
MOC_DIR = $$DESTDIR/
RCC_DIR = $$DESTDIR/
UI_DIR = $$DESTDIR/
main.cpp
#include "mainwindow.h"
#include <QApplication>
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 "graphdata.h"
class MainWindow : public QMainWindow {
Q_OBJECT
QThread thread;
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
signals:
void start();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
resize(400,300);
auto graph = new Q3DScatter;
auto container = QWidget::createWindowContainer(graph);
setCentralWidget(container);
auto data = new GraphData(graph);
data->moveToThread(&thread);
connect(this, &MainWindow::start, data, &GraphData::start);
thread.start();
emit start();
}
MainWindow::~MainWindow() {
thread.quit();
thread.wait();
}
graphdata.h
class GraphData : public QObject {
Q_OBJECT
Q3DScatter* m_graph;
QCustom3DItem* item;
public:
explicit GraphData(Q3DScatter* m_graph);
public slots:
void start();
void setData(int scale);
};
#endif // GRAPHDATA_H
graphdata.cpp
#include "graphdata.h"
GraphData::GraphData(Q3DScatter* graph) : m_graph(graph){}
void GraphData::start() {
item = new QCustom3DItem;
item->setMeshFile(QStringLiteral(":mesh.obj"));
m_graph->addCustomItem(item);
}
void GraphData::setData(int scale) {
// item->setScaling();
}
mesh.qrc
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>mesh.obj</file>
</qresource>
</RCC>
mesh.obj
# Blender v2.80 (sub 75) OBJ File: ''
# www.blender.org
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 0.500000
vt 0.625000 0.250000
vt 0.625000 0.750000
vt 0.625000 1.000000
vt 0.375000 0.750000
vt 0.875000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
s off
f 5/1/1 3/2/1 1/3/1
f 3/4/2 8/5/2 4/6/2
f 7/7/3 6/8/3 8/5/3
f 2/9/4 8/10/4 6/8/4
f 1/11/5 4/12/5 2/13/5
f 5/14/6 2/9/6 6/15/6
f 5/1/1 7/16/1 3/2/1
f 3/4/2 7/7/2 8/5/2
f 7/7/3 5/17/3 6/8/3
f 2/9/4 4/18/4 8/10/4
f 1/11/5 3/19/5 4/12/5
f 5/14/6 1/20/6 2/9/6
这似乎正在工作,尽管有警告,QCustom3DItem
在另一个线程上:
QObject::setParent: Cannot set parent, new parent is in a different thread
[我的理解是m_graph->addCustomItem(item)
正在尝试更改item
父对象,但失败了。我应该如何处理?
通过处理另一个线程上的自定义项目,我应该期望更好的性能吗?
Qt适用于原型设计或非性能关键的代码。但是,其面向对象的方法与硬件的工作方式不符,因此很难编写高效的代码。
您最好的选择是覆盖绘图代码,以便一次调用即可渲染所有条形图。如果需要支持旧硬件,则可以生成具有所有顶点的VBO,然后通过一个glDrawArrays
调用发送。如果最近的硬件还可以,那么您可以通过实例化并从纹理中获取条高来在GPU上生成所有网格。在后一种情况下,您只需要每帧发送10,000个float,就带宽而言,这就算什么了。
底线:对于现代GPU而言,实时渲染10,000个多维数据集是小菜一碟。 Qt是您的瓶颈。