0

I have a QT project that uses the class called QtVTKViewer. All the QWidgets in the project use QtVTKViewer and added in the stackwidget of QT. The first QWidget allows the user to add and adjust vtkObjects to the vtkrenderer of QVTKWidget, and calls Render() of QVTKWidget's vtkRenderWindow every time when an vtkObject is added or adjusted, so that the screen can be updated in real time. The second QWidget can display multiple QtVTKViewers and requires a continuous call to Render() of the vtkRenderWindow. When users return to the first QWidget after staying on the second QWidget for more than two hours and want to add or adjust vtkObjects, they will find that QtVTKViewer's Render doesn’t work to update the screen and the user's actions cannot be displayed instantly.

The QT version is 5.12.8 and VTK version is 8.0.0.

Here is the code of QtVTKViewer:

class QtVTKViewer : public QWidget
{
    Q_OBJECT
    
public: 
    QtVTKViewer(QWidget *parent = nullptr);
    ~QtVTKViewer();

    void Render();
    
    QVTKWidget* pViewer;
    vtkSmartPointer<vtkRenderer> pRenderer;
}

QtVTKViewer::QtVTKViewer(QWidget *parent): QWidget(parent)
{
    pRenderer = vtkSmartPointer<vtkRenderer>::New();

    auto pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    pRenderWindow->AddRenderer(pRenderer);

    pViewer = new QVTKWidget(this);
    pViewer->SetRenderWindow(pRenderWindow);
}

QtVTKViewer::~QtVTKViewer()
{
    pRenderer->RemoveAllViewProps();
}

void QtVTKViewer::Render()
{
    pRenderer->GetRenderWindow()->GetInteractor()->Render();
    //Using pRenderer->GetRenderWindow()->Render() cannot solve the problem.
}

I have found that when all the Render() on the second QWidget are removed, the QtVTKViewer in the first QWidget will work properly, but this does not meet the other requirements of the project. Some QWidget’s function such as update() and repaint() cannot solve the problem.

GodfreyA
  • 1
  • 1

1 Answers1

0

To the best of my knowledge, lots of Qt/VTK examples first calls QVTKWidget::SetRenderWindow() to a vtkRenderWindow, and then calls functions on the vtkRenderWindow. For example, giving it a vtkRenderer. It seems like QVTKWidget should do something before the user modify the vtkRenderWindow's state.

You can refer to https://examples.vtk.org/site/Cxx/Qt/BorderWidgetQt/, which calls QVTKWidget::SetRenderWindow() ASAP, just after the creation of the vtkRenderWindow.

I suggest you to change the order of the statements to

QtVTKViewer::QtVTKViewer(QWidget *parent)
{
    pViewer = new QVTKWidget(this);
    auto pRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    pViewer->SetRenderWindow(pRenderWindow);

    pRenderer = vtkSmartPointer<vtkRenderer>::New();
    pRenderWindow->AddRenderer(pRenderer);
}
Fulva
  • 1