问题
I want to make a 3D chart with bars, the bar color depends on its size. Both Qt bar and scatter graph types are close to what I'm looking for. I ended up creating a chart based on Q3DScatter
and adding QCustom3DItem
to draw the bars, so I can set a mesh item and color to each item. I have one item in each position of the chart. Let's say it's a 100x100 chart, meaning there are 10 000 bars (custom items).
I want to redraw the entire chart multiple times per second. By redraw I mean every item will change its size and color. To set item size I call setScalling(). Because scalling works by keeping the item center position (and I want to keep the bar base position) then I have to call setPosition just after scalling. And to set color I call setTextureImage(). So, multiple times per second, code like the following get's called:
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);
}
This works almost as expected. Problem is not fast enough. Any hints on how to make it faster?
I tried to move custom items to another thread.
In order to move processsing (i.e. scalling) of QCustom3DItem
out of main (gui) thread I do:
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
This looks like to be working, the QCustom3DItem
is on another thread, though there is the warning:
QObject::setParent: Cannot set parent, new parent is in a different thread
My understanding is that m_graph->addCustomItem(item)
is trying to change item
parent and is failing. How should I deal with this?
Should I expect better performance by processing custom items on another thread?
来源:https://stackoverflow.com/questions/59597182/custom-chart-based-on-q3dscatter-with-qcustom3ditem-going-slow