render 2D content in QVTKOpenGLNativeWidget

I have a question puzzles me for a long time. The class FormResliceViewer derives from QVTKOpenGLNativeWidget. vtkResliceImageViewer is used, with SetRenderWindow() by the FormResliceViewer object. Image reslice can be rendered well in the Viewer. Actually, there are 3 image reslice viewers. I defined them in a for loop. I choose one of the viewers to describe my question.

class FormResliceViewer : public QVTKOpenGLNativeWidget
{
public:
    FormResliceViewer(QWidget* parent=nullptr);

    void setImageFileName(QString fileName);
    void setBorderColor(QColor color);

protected:
    void paintGL()override;
//    bool renderVTK()override;
//    void paintEvent(QPaintEvent * e)override;

// some other members
......
}

Code in header:
vtkSmartPointer m_resliceImageViewers[3];
FormResliceViewer* m_formResliceViewers[3];
vtkSmartPointer m_imageRenderWindows[3];

Code in main initial function:

    for (int i=0; i<3; ++i)
    {
        m_imageRenderWindows[i] = vtkGenericOpenGLRenderWindow::New();

        m_resliceImageViewers[i] = vtkSmartPointer<vtkResliceImageViewer>::New();
        m_resliceImageViewers[i]->SetRenderWindow(m_imageRenderWindows[i]);

        m_formResliceViewers[i] = new FormResliceViewer();
        m_formResliceViewers[i]->SetRenderWindow(m_imageRenderWindows[i]);
        m_formResliceViewers[i]->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);

        m_resliceImageViewers[i]->SetupInteractor(m_imageRenderWindows[i]->GetInteractor());

        vtkResliceCursorLineRepresentation *rep = vtkResliceCursorLineRepresentation::SafeDownCast(
                    m_resliceImageViewers[i]->GetResliceCursorWidget()->GetRepresentation());
        rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i);

        int color[3] = {0, 0, 0};
        color[i] = 255;
        QColor qColor(color[0],color[1],color[2]);
        m_formResliceViewers[i]->setBorderColor(qColor);
//      m_resliceImageViewers[i]->SetResliceCursor(m_resliceImageViewers[0]->GetResliceCursor());

    }

p2

Now I want to add green border(2D content) to the Viewer. I override the function paintGL().

void FormResliceViewer::paintGL()
{
    QPainter painter(this);
    painter.begin(this);
    QPen pen;
    pen.setColor(m_borderColor);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawRect(0, 0, width(), height());

    QVTKOpenGLNativeWidget::paintGL();

}

But I can NOT see any border. If I comment the last line (QVTKOpenGLNativeWidget::paintGL();). I can see the green border appear, but the image reslice disappear. That’s not the result I want.

void FormResliceViewer::paintGL()
{
    QPainter painter(this);
    painter.begin(this);
    QPen pen;
    pen.setColor(m_borderColor);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawRect(0, 0, width(), height());

//    QVTKOpenGLNativeWidget::paintGL();

}

p1

I try to override function renderVTK() and paintEvent() with the same code above, but all fail. I guess there must be something I have ignore that to keep the image reslice and the border exitence. Or native Qt 2D content drawing API is not supported in VTK? I would appreciate it if someone could give me some demo code or advice!

P.S. My development environment is VTK 8.2.0 in ubuntu 18.04.

I have not used this approach of painting on top of VTK using QPainter, so I can’t say whether it’s supported or not, but don’t you have to put your painting code after the base class call, as to paint on top of what VTK is drawing?

An alternative approach would be to add another layer to your render window, create a renderer associated with that layer and into that renderer add a vtkActor2D representing your border. That’s what we do in our application to draw some screen space 2D graphics on top of a volume rendering.

I call paintGL() first and then put the painting code. The green border still does not appear. Maybe VTK drawing is always on the top of the render window so that other api paintings can not be seen, I guess.

Using vtkActor2D maybe a good way to solve the problem. But what I exactly want to draw is something as “widget” instead of “scene object”. Besides the border, maybe I will probably put more other “widgets” in the viewer next. If any other solution can not be found, I will take your advice. :grinning: