Using QVTKOpenGLWidget with vtkContextItem-derived class

Hi,

I’m really new to VTK and I’m in the process of both reading the VTK online book and also trying to get a simple Qt-based application using a vtkContextItem-derived class to draw to a vtkContext2D. Anyway, I’ve been able to get a window to show up, but the vtkContextItem-derived object’s Paint() method never gets called and nothing displays other than a black window. I’ve looked online for examples and there just aren’t may using QVTKOpenGLWidget and a vtkContextItem-derived class. I was curious if someone knew what I am missing to tie everything together properly. Does anyone know?

My test application’s code is below for reference.

Many, many thanks for the help!

Sincerely,

Kevin Hall

#define vtkRenderingCore_AUTOINIT 2(vtkRenderingOpenGL2, vtkInteractionStyle)
#define vtkRenderingVolume_AUTOINIT 1(vtkRenderingVolumeOpenGL)

#include <QApplication>
#include <vtkNew.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkBrush.h>
#include <vtkContextActor.h>
#include <vtkContextItem.h>
#include <vtkContextScene.h>
#include <vtkObjectFactory.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkContext2D.h>
#include <QVTKOpenGLWidget.h>

class MyDrawing : public vtkContextItem
{
public:
    static MyDrawing *New();
    vtkTypeMacro(MyDrawing, vtkContextItem);
    virtual bool Paint(vtkContext2D* painter)
    {
        painter->GetBrush()->SetColor(255, 0, 0);
        painter->DrawRect(20,20,40,40);
        return true;
    }
};

vtkStandardNewMacro(MyDrawing);

int main(int argc, char** argv)
{
    QCoreApplication::addLibraryPath("../../../bin/Qt");

    QApplication app(argc, argv);

    QVTKOpenGLWidget widget;
    widget.resize( 256, 256 );

    vtkNew<vtkContextActor> cactor;
    vtkNew<MyDrawing>		drawing;
    vtkNew<vtkRenderer>		renderer;

    cactor->GetScene()->AddItem(drawing);
    renderer->AddActor( cactor );

    auto renderWindow = widget.GetRenderWindow();
    vtkNew<vtkRenderWindowInteractor> interactor;
    interactor->SetRenderWindow(renderWindow);

    widget.GetRenderWindow()->AddRenderer( renderer );
    widget.show();

    app.exec();

    return EXIT_SUCCESS;
}

We use ctkVTKChartView class (in CTK library) to show charts in our Qt-based application. You can find an example here.

1 Like

Hi Kevin,

I got your test case working (see below). I think what was mostly missing was to set up a QSurfaceFormat appropriate for QVTKOpenGLWidget.

ctx.cpp

#include <QApplication>
#include <QSurfaceFormat>

#include <vtkNew.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkBrush.h>
#include <vtkContextActor.h>
#include <vtkContextItem.h>
#include <vtkContextScene.h>
#include <vtkObjectFactory.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkContext2D.h>
#include <QVTKOpenGLWidget.h>

class MyDrawing : public vtkContextItem
{
public:
    static MyDrawing *New();
    vtkTypeMacro(MyDrawing, vtkContextItem);
    virtual bool Paint(vtkContext2D* painter)
    {
        painter->GetBrush()->SetColor(255, 0, 0);
        painter->DrawRect(20,20,40,40);
        return true;
    }
};

vtkStandardNewMacro(MyDrawing);

int main(int argc, char** argv)
{
    QCoreApplication::addLibraryPath("../../../bin/Qt");

    QSurfaceFormat::setDefaultFormat(QVTKOpenGLWidget::defaultFormat());

    QApplication app(argc, argv);

    vtkNew<MyDrawing> drawing;

    vtkNew<vtkContextActor> cactor;
    cactor->GetScene()->AddItem(drawing);

    vtkNew<vtkRenderer> renderer;
    renderer->AddActor(cactor);

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

    QVTKOpenGLWidget widget;
    widget.SetRenderWindow(window.Get());
    widget.resize( 256, 256 );
    widget.show();

    return app.exec();
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(ctx)

find_package(Qt5Widgets REQUIRED)

find_package(VTK 8.2.0 REQUIRED COMPONENTS
    vtkGUISupportQt
    vtkInteractionStyle
    vtkRenderingCore
    vtkRenderingContext2D
    vtkRenderingContextOpenGL2
    vtkRenderingFreeType
    vtkRenderingOpenGL2
)

add_executable(ctx WIN32
    ctx.cpp
)

target_link_libraries(ctx PRIVATE
    Qt5::Widgets
    vtkGUISupportQt
    vtkInteractionStyle
    vtkRenderingCore
    vtkRenderingContext2D
    vtkRenderingContextOpenGL2
    vtkRenderingFreeType
    vtkRenderingOpenGL2
)

target_include_directories(ctx SYSTEM PRIVATE
    ${VTK_INCLUDE_DIRS}
)

target_compile_definitions(ctx PRIVATE
    ${VTK_DEFINITIONS}
)

Result

result

Hope that helps.

1 Like

Note also from the QVTKOpenGLWidget docs:

Unlike QVTKOpenGLNativeWidget, QVTKOpenGLWidget does not require that the default surface format for the application be changed. One can simply specify the needed QSurfaceFormat for the specific QVTKOpenGLWidget instance by calling QVTKOpenGLWidget::setFormat before the widget is initialized.

So

widget.setFormat(QVTKOpenGLWidget::defaultFormat());

will also work.

(Note the above is true for VTK 8.2.0 and higher. In versions prior, QVTKOpenGLNativeWidget was the only QOpenGLWidget-based widget, and it was called QVTKOpenGLWidget, and I think it required you to change the application default format)

Thank you Elvis. That was very helpful and got me unstuck! :slight_smile:

Wow, I didn’t even know about the CTK library. There’s a lot of really cool things there. Once I get my feet under VTK, I’ll certainly take a look at that. Thank you!