Hi !
I have an issue deleting and replacing 3Dscatter and 3DSurface plots in Qt in C++. I'm working with QtDataVisualization in C++ and I've been stuck for half a year with the following problem : when I try to replace a Q3DScatter graph A by a Q3DScatter graph B, the deletion of graph A makes graph B unreadable if B is built before A is destroyed.

I'm trying to figure out at which point graph A and graph B interact with each other while they are not supposed to. I have a sample code here that is close to a MWE. I have let the function "build" in, but what it does is just initializing the graph and storing its address in a pointer, m3DGraph.

If PROBLEM is set to false, deletion step and creation of the next data are exchanged, and the issue does not happen, but it's not what I'm looking for since I want to update my display once the data is computed, and to be able to change the type of graph in the m3DImageHolder.

I think it's worth mentionning that I've done the test with a Q3DSurface graph and there is a similar issue : with Q3DScatter, the graph doesn't display, with Q3DSurface, the grid disappears.

I already posted this to StackOverflow, but did not get any answer. I link the question here in case there are further discussions Stack Overflow Question



Here is the header:
Qt Code:
  1. #include <QDialog>
  2. #include <QtWidgets/QLabel>
  3. #include <QtWidgets/QVBoxLayout>
  4. #include <QtDataVisualization/Q3DScatter>
  5. #include <QtDataVisualization/Q3DSurface>
  6.  
  7. namespace QtD = QtDataVisualization;
  8.  
  9. class ViewerTest : public QDialog{
  10. private:
  11. QPushButton *mHide,*mNewScat,*mNewSurf;
  12.  
  13. QVBoxLayout *m3DLayoutHolder;
  14. QHBoxLayout *mButtonsLayout;
  15. QVBoxLayout *mMainLayout;
  16.  
  17. QWidget *m3DImageHolder;
  18.  
  19. QtD::Q3DScatter *m3DGraph;
  20. QtD::Q3DSurface *m3DGraphSurface;
  21. public:
  22. enum TYPE{HIDE_BOTH,SCATTER,SURF};
  23.  
  24. ViewerTest();
  25. void buildScatter(){manageGraphs(TYPE::SCATTER);};
  26. void buildSurface(){manageGraphs(TYPE::SURF);};
  27. void hideAll(){manageGraphs();};
  28. void build(TYPE type);
  29. void manageGraphs(TYPE type=HIDE_BOTH); //Shows or hide graphs
  30. };
To copy to clipboard, switch view to plain text mode 


Here is the .cpp
Qt Code:
  1. #include "test3DvisuData.h"
  2.  
  3. #include <QPushButton>
  4. #include <iostream>
  5. #include <QtDataVisualization/qcustom3dlabel.h>
  6. #include <QtDataVisualization/q3dscatter.h>
  7. #include <QtDataVisualization/q3dsurface.h>
  8. #include <QtDataVisualization/QCustom3DVolume>
  9. #include <QtDataVisualization/Q3DInputHandler>
  10. #include <QtDataVisualization/QHeightMapSurfaceDataProxy>
  11. #include <QApplication>
  12.  
  13. #define PROBLEM true
  14. /// Short class for debugging objects creation
  15. template<typename T> class GraphTest: public T{
  16. const int mLabel;
  17. static int label;
  18. std::string name;
  19. public:
  20. GraphTest(const std::string & in):T(),mLabel(label++),name(in){
  21. std::cout<<" ctor "<< name <<mLabel<< std::endl;
  22. };
  23. ~GraphTest(){
  24. std::cout<<" ~dtor "<< name << mLabel<<std::endl;
  25. };
  26. };
  27.  
  28. template <typename T>int GraphTest<T>::label = 0;
  29.  
  30.  
  31. ViewerTest::ViewerTest():m3DImageHolder(nullptr),m3DGraph(nullptr),m3DGraphSurface(nullptr){
  32. mHide = new QPushButton("hide",this);
  33. mNewScat = new QPushButton("scat",this);
  34. mNewSurf = new QPushButton("surf",this);
  35.  
  36. m3DLayoutHolder = new QVBoxLayout();
  37. mButtonsLayout = new QHBoxLayout();
  38. mMainLayout = new QVBoxLayout(this);
  39. setLayout(mMainLayout);
  40. mMainLayout->addLayout(mButtonsLayout);
  41. mMainLayout->addLayout(m3DLayoutHolder);
  42.  
  43. mButtonsLayout->addWidget(mHide);
  44. mButtonsLayout->addWidget(mNewScat);
  45. mButtonsLayout->addWidget(mNewSurf);
  46.  
  47. connect(mNewSurf,&QPushButton::released,this,&ViewerTest::buildSurface);
  48. connect(mNewScat,&QPushButton::released,this,&ViewerTest::buildScatter);
  49. connect(mHide,&QPushButton::released,this,&ViewerTest::hideAll);
  50.  
  51. }
  52.  
  53. ///This part is just the data construction
  54.  
  55. void ViewerTest::build(TYPE type) {
  56. if(type==SCATTER) {
  57. m3DGraph = new /*QtD::Q3DScatter();*/GraphTest<QtD::Q3DScatter>("inData3D");
  58. m3DGraph->scene()->activeCamera()->setCameraPreset( QtD::Q3DCamera::CameraPresetIsometricRight );
  59. m3DGraph->setOrthoProjection(true);
  60. QtD::QCustom3DVolume *vol = new QtD::QCustom3DVolume;
  61. vol->setScaling(
  62. QVector3D(m3DGraph->axisX()->max() - m3DGraph->axisX()->min(),
  63. (m3DGraph->axisY()->max() - m3DGraph->axisY()->min()) * 1.0f,
  64. m3DGraph->axisZ()->max() - m3DGraph->axisZ()->min()));
  65. vol->setScalingAbsolute(false);
  66.  
  67. // Build the data
  68. unsigned int height(20),width(20),depth(20);
  69. QVector<uchar> *vectorData = new QVector<uchar>(height * width * depth * 4, 0);
  70. vol->setTextureWidth(width);vol->setTextureHeight(height);vol->setTextureDepth(depth);
  71.  
  72. vol->setTextureFormat(QImage::Format_ARGB32);
  73. for (int z = 0; z < height; z++) {
  74. for (int y = 0; y < depth; y++) {
  75. for (int x = 0; x < width; x++) {
  76. for( int c = 0; c<4; c++){
  77. (*vectorData)[(x + width * z + width * height * y) * 4 + c] =
  78. c==0?x*5:(c==1?y*5:(c==2?z*5:20));
  79. }
  80. }
  81. }
  82. }
  83. vol->setTextureData(vectorData);
  84. m3DGraph->addCustomItem(vol);
  85. }
  86.  
  87. ///// ------------------
  88. else if(type==SURF){
  89. QImage image = QImage(20,20,QImage::Format_Grayscale8);
  90. for(uint x=0; x<20; x++){
  91. for(uint y=0; y<20; y++){
  92. image.setPixelColor(x,y,QColor(x*y));
  93. }
  94. }
  95. QtD::QHeightMapSurfaceDataProxy *proxy = new QtD::QHeightMapSurfaceDataProxy(image);
  96. QtD::QSurface3DSeries *serie = new QtD::QSurface3DSeries(proxy);
  97. serie->setDrawMode(QtD::QSurface3DSeries::DrawSurface);
  98.  
  99. m3DGraphSurface = new GraphTest<QtD::Q3DSurface>("inData3DSurface");
  100. m3DGraphSurface->addSeries(serie);
  101. m3DGraphSurface->seriesList().at(0)->setColorStyle( QtD::Q3DTheme::ColorStyleRangeGradient );
  102.  
  103. }
  104.  
  105. }
To copy to clipboard, switch view to plain text mode 


and here is the problematic function
Qt Code:
  1. void ViewerTest::manageGraphs(TYPE type) {
  2. #if PROBLEM
  3. build(type); //---> no error thrown, but graph don't display
  4. #endif
  5.  
  6. // delete previous
  7. m3DLayoutHolder->removeWidget(m3DImageHolder);
  8. delete m3DImageHolder;
  9. m3DImageHolder= nullptr;
  10.  
  11. #if PROBLEM
  12. #else
  13. build(type); ///---> display works perfectly
  14. #endif
  15.  
  16. if(type == SCATTER) {
  17. m3DImageHolder = QWidget::createWindowContainer(m3DGraph, this);
  18. } else if(type==SURF){
  19. m3DImageHolder = QWidget::createWindowContainer(m3DGraphSurface,this);
  20. }
  21. if(type != TYPE::HIDE_BOTH) {
  22. m3DLayoutHolder->addWidget(m3DImageHolder);
  23. m3DImageHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  24. }
  25.  
  26. }
  27.  
  28. // Just a Widget with two buttons (hide/new)
  29. // OnClick, load a new3D dataset
  30.  
  31. int main(int argc, char** argv){
  32. QApplication qApplication( argc, argv);
  33.  
  34. ViewerTest viewerTest;
  35. return viewerTest.exec();
  36. }
To copy to clipboard, switch view to plain text mode