Results 1 to 3 of 3

Thread: Issue deleting and replacing 3Dscatter and 3DSurface plots in Qt

  1. #1
    Join Date
    Jul 2020
    Posts
    11
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt5

    Default Issue deleting and replacing 3Dscatter and 3DSurface plots in Qt

    Hi everybody,
    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.

    Here is a bit of code below, and I let a link to my StackOverflow question in case anyone gives an answer months after I stopped working on this.

    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 

    If you have any explication of how could I get this to work...? Big thanks in advance, cheers !
    Last edited by Stophe; 9th July 2020 at 16:18. Reason: Last post did not work

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Issue deleting and replacing 3Dscatter and 3DSurface plots in Qt

    With just a quick read, the only thing that sticks out is this in line 8 of your last code block:
    Qt Code:
    1. delete m3DImageHolder;
    To copy to clipboard, switch view to plain text mode 
    instead of:
    Qt Code:
    1. m3DImageHolder->deleteLater();
    To copy to clipboard, switch view to plain text mode 
    Calling delete on a QWidget instance that may still be in use (even though in the previous statement you removed it from what is presumably a parent object) does not allow the Qt event loop to run and process any events associated with either removing the instance or deleting it because delete immediately invalidates the instance and its contents. Calling QObject::deleteLater() schedules the instance for deletion during a future cycle through the event loop, but also allows Qt to first process any events the removal causes using the still-valid instance.
    Last edited by d_stranz; 9th July 2020 at 19:06.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    Stophe (13th July 2020)

  4. #3
    Join Date
    Jul 2020
    Posts
    11
    Thanks
    4
    Thanked 1 Time in 1 Post
    Qt products
    Qt5

    Default Re: Issue deleting and replacing 3Dscatter and 3DSurface plots in Qt

    Quote Originally Posted by d_stranz View Post
    With just a quick read, the only thing that sticks out is this in line 8 of your last code block:
    Qt Code:
    1. m3DImageHolder->deleteLater();
    To copy to clipboard, switch view to plain text mode 
    Thanks for this advice ! I'll be carefull about that now.
    I've applied this patch, but unfortunately... I still get the same error.
    I changed to
    Qt Code:
    1. if(m3DImageHolder) {
    2. m3DLayoutHolder->removeWidget(m3DImageHolder);
    3. m3DImageHolder->deleteLater();
    4. m3DImageHolder = nullptr;
    5. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Stophe; 13th July 2020 at 13:05.

Similar Threads

  1. QHttp Post work inkorect
    By Pablik in forum Qt Programming
    Replies: 12
    Last Post: 29th January 2013, 13:19
  2. Testing Qt-Software with a GUI Testing Tool
    By nightghost in forum Qt Programming
    Replies: 8
    Last Post: 22nd February 2012, 08:43
  3. Replies: 6
    Last Post: 25th May 2010, 11:42
  4. GUI Testing
    By larry104 in forum Qt Programming
    Replies: 1
    Last Post: 13th September 2007, 14:46

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.