Qt + VTK : Window reopens when adding a VTK widget, prevents correct display in Docker container

Hello !
I am working on a visualization app that I would like to be easily sharable via Docker. The application makes use of the VTK+Qt widgets.

I noticed a unexpected behaviour with these widgets: when adding a VTK widget to a Qt window that is already rendered on screen, this window closes and reopens with the new widget at the correct place. This only happens the first time a VTK widget is added to the application layout, the subsequent additions do not cause closing and reopening of the GUI.

This behaviour caused me no harm before trying to share the application with Docker. Now that I am trying to build a container running the application, I can share the host’s Xorg session with the container to display my GUI, but the application stops rendering at the moment it closes and reopens when adding a VTK widget.

Is the described behaviour (closing and reopening the window) normal ? Can it be avoided ? Or is it possible to have Docker keeping rendering the application after it happens ? (Maybe I am not on the right forum to ask this last question)

I am using Debian 12, with Qt6 and VTK 9.2.6, below are the sources to reproduce the behaviour I just described.

Thank you for any help or advice !

main.cpp

#include <QApplication>
#include <QVTKOpenGLWindow.h>

#include "MainWindow.h"

int main(int argc, char** argv)
{
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLWindow::defaultFormat());
    QApplication app(argc, argv);
    MainWindow window;
    window.show();
    return QApplication::exec();
}

MainWindow.h

#pragma once

#include <QWidget>
#include <QPushButton>

class MainWindow : public QWidget
{
Q_OBJECT

private:
    QPushButton* start_vtk_button;

public:
    MainWindow();

public slots:
    void start_vtk();
};

MainWindow.cpp

#include "MainWindow.h"

#include <QVBoxLayout>
#include <QVTKOpenGLNativeWidget.h>

#include <vtkNamedColors.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkRenderer.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

MainWindow::MainWindow()
{
    auto layout = new QVBoxLayout();
    start_vtk_button = new QPushButton("VTK");
    connect(start_vtk_button, &QPushButton::clicked, this, &MainWindow::start_vtk);
    layout->addWidget(start_vtk_button);
    this->setLayout(layout);
}

void MainWindow::start_vtk()
{
    vtkNew<vtkNamedColors> colors;

    std::array<unsigned char, 4> bkg{{26, 51, 102, 255}};
    colors->SetColor("BkgColor", bkg.data());

    vtkNew<vtkCylinderSource> cylinder;
    cylinder->SetResolution(8);

    vtkNew<vtkPolyDataMapper> cylinderMapper;
    cylinderMapper->SetInputConnection(cylinder->GetOutputPort());

    vtkNew<vtkActor> cylinderActor;
    cylinderActor->SetMapper(cylinderMapper);
    cylinderActor->GetProperty()->SetColor(colors->GetColor4d("Tomato").GetData());
    cylinderActor->RotateX(30.0);
    cylinderActor->RotateY(-45.0);

    vtkNew<vtkRenderer> renderer;
    renderer->AddActor(cylinderActor);
    renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
    renderer->ResetCamera();
    renderer->GetActiveCamera()->Zoom(1.5);

    vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
    renderWindow->AddRenderer(renderer);

    auto interactor = vtkSmartPointer<QVTKInteractor>::New();
    interactor->SetRenderWindow(renderWindow);
    interactor->Initialize();

    auto render_widget = new QVTKOpenGLNativeWidget();
    render_widget->setRenderWindow(renderWindow);
    this->layout()->addWidget(render_widget);
    render_widget->show();
    renderWindow->Render();
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.23)

project(TestVTKBug VERSION 1.0)

set(CMAKE_CXX_STANDARD 17)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

set(SOURCES
        main.cpp
        MainWindow.cpp)

find_package(Qt6 COMPONENTS Widgets Core Gui Concurrent REQUIRED)
find_package(VTK REQUIRED)

add_executable(${PROJECT_NAME} ${SOURCES})

target_link_libraries(${PROJECT_NAME}
        ${VTK_LIBRARIES}
        Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Concurrent)

vtk_module_autoinit(
    TARGETS ${PROJECT_NAME}
    MODULES ${VTK_LIBRARIES}
)

Dockerfile

# Building the image:
# docker build -t test .

# Running the container with access to host's Xorg server:
# docker run -it --rm --net=host --env="DISPLAY" --volume="$HOME/.Xauthority:/root/.Xauthority:rw" test

FROM debian:bookworm
LABEL authors="SarevokAnchev"

RUN apt-get update

RUN apt-get install -y cmake \
                      git \
                      build-essential \
                      qt6-base-dev \
                      qt6-base-dev-tools \
                      libgl1-mesa-dev

#Build VTK
RUN mkdir VTK \
    && cd VTK \
    && mkdir src \
    && mkdir bin \
    && mkdir build \
    && git clone --branch v9.2.6 https://github.com/Kitware/VTK.git src \
    && cd bin \
    && cmake ../src/ -DCMAKE_INSTALL_PREFIX="../build/" -DBUILD_SHARED_LIBS=OFF -DVTK_BUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DVTK_GROUP_ENABLE_Qt=YES -DVTK_MODULE_ENABLE_VTK_GUISupportQtQuick=NO \
    && make -j4 \
    && make install \
    && cd .. \
    && cd ..

RUN mkdir TestVTKBug

COPY ./ TestVTKBug/

RUN cd TestVTKBug \
    && mkdir bin \
    && mkdir build \
    && cd bin \
    && cmake .. -DCMAKE_BUILD_TYPE=Release -DVTK_DIR="../../VTK/build/lib/cmake/vtk-9.2/" \
    && make -j4 \
    && cd .. \
    && cd ..

ENTRYPOINT ["TestVTKBug/bin/TestVTKBug"]