Skip to content

RenderWindowUISingleInheritance

vtk-examples/Cxx/Qt/RenderWindowUISingleInheritance


Description

Using a QVTKOpenGLNativeWidget with the Qt Single Inheritance model. This cleanly separates the public interface of the class from its internals.

The main widget is derived from from QMainWindow and the class Ui::RenderWindowUISingleInheritance becomes a variable in the class.

The procedure is:

  • In the header file RenderWindowUISingleInheritance.h forward declare the class Ui_RenderWindowUISingleInheritance and create a private variable in the class:
private:
  // Designer form
  Ui_RenderWindowUISingleInheritance* ui;
  • In the source file RenderWindowUISingleInheritance.cxx, assign and initialise in the constructor:
  this->ui = new Ui_RenderWindowUISingleInheritance;
  this->ui->setupUi(this);

This approach also ensures that when CMAKE_AUTOUIC is set to ON and subfolders are used we get a build with no errors.

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

RenderWindowUISingleInheritance.cxx

#include "RenderWindowUISingleInheritance.h"
#include "ui_RenderWindowUISingleInheritance.h"

#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkVersion.h>

#if VTK_VERSION_NUMBER >= 89000000000ULL
#define VTK890 1
#endif

// Constructor
RenderWindowUISingleInheritance::RenderWindowUISingleInheritance(
    QWidget* parent)
  : QMainWindow(parent), ui(new Ui::RenderWindowUISingleInheritance)
{
  this->ui->setupUi(this);

  vtkNew<vtkNamedColors> colors;

  vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
#if VTK890
  this->ui->qvtkWidget->setRenderWindow(renderWindow);
#else
  this->ui->qvtkWidget->SetRenderWindow(renderWindow);
#endif

  // Sphere
  vtkNew<vtkSphereSource> sphereSource;
  sphereSource->Update();
  vtkNew<vtkPolyDataMapper> sphereMapper;
  sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
  vtkNew<vtkActor> sphereActor;
  sphereActor->SetMapper(sphereMapper);
  sphereActor->GetProperty()->SetColor(colors->GetColor4d("Tomato").GetData());

  // VTK Renderer
  vtkNew<vtkRenderer> renderer;
  renderer->AddActor(sphereActor);
  renderer->SetBackground(colors->GetColor3d("SteelBlue").GetData());

  // VTK/Qt wedded
#if VTK890
  this->ui->qvtkWidget->renderWindow()->AddRenderer(renderer);
  this->ui->qvtkWidget->renderWindow()->SetWindowName(
      "RenderWindowUISingleInheritance");
#else
  this->ui->qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
  this->ui->qvtkWidget->GetRenderWindow()->SetWindowName(
      "RenderWindowUISingleInheritance");
#endif
  // Set up action signals and slots
  connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit()));
}

RenderWindowUISingleInheritance::~RenderWindowUISingleInheritance()
{
  delete this->ui;
}

void RenderWindowUISingleInheritance::slotExit()
{
  qApp->exit();
}

RenderWindowUISingleInheritance.h

#ifndef RenderWindowUISingleInheritance_H
#define RenderWindowUISingleInheritance_H

#include <vtkSmartPointer.h>

#include <QMainWindow>

/*
 * See "The Single Inheritance Approach" in this link:
 * [Using a Designer UI File in Your C++
 * Application](https://doc.qt.io/qt-5/designer-using-a-ui-file.html)
 */
namespace Ui {
class RenderWindowUISingleInheritance;
}

class RenderWindowUISingleInheritance : public QMainWindow
{
  Q_OBJECT
public:
  // Constructor/Destructor
  explicit RenderWindowUISingleInheritance(QWidget* parent = nullptr);
  virtual ~RenderWindowUISingleInheritance();

private:
  // Designer form
  Ui::RenderWindowUISingleInheritance* ui;

public slots:
  void slotExit();
};

#endif

RenderWindowUISingleInheritance.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>RenderWindowUISingleInheritance</class>
 <widget class="QMainWindow" name="RenderWindowUISingleInheritance">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>541</width>
    <height>583</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>RenderWindowUISingleInheritance</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QVTKOpenGLNativeWidget" name="qvtkWidget">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>20</y>
      <width>511</width>
      <height>541</height>
     </rect>
    </property>
   </widget>
  </widget>
  <action name="actionOpenFile">
   <property name="enabled">
    <bool>true</bool>
   </property>
   <property name="text">
    <string>Open File...</string>
   </property>
  </action>
  <action name="actionExit">
   <property name="text">
    <string>Exit</string>
   </property>
  </action>
  <action name="actionPrint">
   <property name="text">
    <string>Print</string>
   </property>
  </action>
  <action name="actionHelp">
   <property name="text">
    <string>Help</string>
   </property>
  </action>
  <action name="actionSave">
   <property name="text">
    <string>Save</string>
   </property>
  </action>
 </widget>
 <customwidgets>
  <customwidget>
   <class>QVTKOpenGLNativeWidget</class>
   <extends>QWidget</extends>
   <header>QVTKOpenGLNativeWidget.h</header>
  </customwidget>
 </customwidgets>
 <resources>

 </resources>
 <connections/>
</ui>

RenderWindowUISingleInheritanceDriver.cxx

#include <QApplication>
#include <QSurfaceFormat>
#include <QVTKOpenGLNativeWidget.h>

#include "RenderWindowUISingleInheritance.h"

int main( int argc, char** argv )
{
  // needed to ensure appropriate OpenGL context is created for VTK rendering.
  QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

  // QT Stuff
  QApplication app( argc, argv );

  RenderWindowUISingleInheritance renderWindowUISingleInheritance;
  renderWindowUISingleInheritance.show();

  return app.exec();
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

if(POLICY CMP0020)
  cmake_policy(SET CMP0020 NEW)
  cmake_policy(SET CMP0071 NEW)
endif()

PROJECT(RenderWindowUISingleInheritance)

find_package(VTK COMPONENTS 
  vtkCommonColor
  vtkCommonCore
  vtkFiltersSources
  vtkInteractionStyle
  vtkRenderingContextOpenGL2
  vtkRenderingCore
  vtkRenderingFreeType
  vtkRenderingGL2PSOpenGL2
  vtkRenderingOpenGL2
  vtkGUISupportQt
  vtkRenderingQt
  QUIET
)

if(NOT VTK_FOUND)
  message(FATAL_ERROR "RenderWindowUISingleInheritance: ${VTK_NOT_FOUND_MESSAGE}")
endif()

if(NOT(vtkGUISupportQt_LOADED OR TARGET VTK::GUISupportQt))
  message(FATAL_ERROR "RenderWindowUISingleInheritance: VTK not built with Qt support.")
endif()

if(NOT DEFINED VTK_QT_VERSION)
  set(VTK_QT_VERSION 5)
endif()

set(qt_components Core Gui Widgets)
if(${VTK_QT_VERSION} VERSION_GREATER_EQUAL 6)
  list(APPEND qt_components OpenGLWidgets)
endif()
list(SORT qt_components)
# We have ui files, so this will also bring in the macro:
#   qt5_wrap_ui or qt_wrap_ui from Widgets.
find_package(Qt${VTK_QT_VERSION} QUIET
  REQUIRED COMPONENTS ${qt_components}
)

foreach(_qt_comp IN LISTS qt_components)
  list(APPEND qt_modules "Qt${VTK_QT_VERSION}::${_qt_comp}")
endforeach()

message (STATUS "VTK_VERSION: ${VTK_VERSION}, Qt Version: ${Qt${VTK_QT_VERSION}Widgets_VERSION}")

if (VTK_VERSION VERSION_LESS "8.90.0")
# Instruct CMake to run moc automatically when needed.
  set(CMAKE_AUTOMOC ON)
else()
# Instruct CMake to run moc and uic automatically when needed.
  set(CMAKE_AUTOMOC ON)
  set(CMAKE_AUTOUIC ON)
endif()

include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})

file(GLOB UI_FILES *.ui)
file(GLOB QT_WRAP *.h)
file(GLOB CXX_FILES *.cxx)

# For VTK versions greater than or equal to 8.90.0:
#  CMAKE_AUTOUIC is ON so we handle uic automatically for Qt targets.
#  CMAKE_AUTOMOC is ON so we handle moc automatically for Qt targets.
# However we have to do the following for VTK versions less than 8.90.0,
#  and we also assume, in this case, that Qt5 is being used.
if (VTK_VERSION VERSION_LESS "8.90.0")
  qt5_wrap_ui(UISrcs ${EXAMPLE}.ui)
endif()

if (VTK_VERSION VERSION_LESS "8.90.0")
  # old system
  include(${VTK_USE_FILE})
  # CMAKE_AUTOMOC in ON so the MOC headers will be automatically wrapped.
  add_executable(RenderWindowUISingleInheritance MACOSX_BUNDLE
    ${CXX_FILES} ${UISrcs} ${QT_WRAP})
  if (Qt${VTK_QT_VERSION}Widgets_VERSION VERSION_LESS "5.11.0")
    qt5_use_modules(RenderWindowUISingleInheritance ${qt_components})
  else()
    target_link_libraries(RenderWindowUISingleInheritance ${qt_modules})
  endif()
  target_link_libraries(RenderWindowUISingleInheritance ${VTK_LIBRARIES})
else()
  # CMAKE_AUTOMOC in ON so the MOC headers will be automatically wrapped.
  add_executable(RenderWindowUISingleInheritance MACOSX_BUNDLE
    ${CXX_FILES} ${UISrcs} ${QT_WRAP})
  if (Qt${VTK_QT_VERSION}Widgets_VERSION VERSION_LESS "5.11.0")
    qt5_use_modules(RenderWindowUISingleInheritance ${qt_components})
  else()
    target_link_libraries(RenderWindowUISingleInheritance ${qt_modules})
  endif()
  target_link_libraries(RenderWindowUISingleInheritance ${VTK_LIBRARIES})
  # vtk_module_autoinit is needed
  vtk_module_autoinit(
    TARGETS RenderWindowUISingleInheritance
    MODULES ${VTK_LIBRARIES}
  )
endif()

Download and Build RenderWindowUISingleInheritance

Click here to download RenderWindowUISingleInheritance and its CMakeLists.txt file. Once the tarball RenderWindowUISingleInheritance.tar has been downloaded and extracted,

 cd RenderWindowUISingleInheritance/build

This example requires Qt and VTK.

If VTK and Qt are installed:

 cmake ..

If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:

 cmake -DVTK_DIR:PATH=/home/me/vtk_build ..

If Qt is not found on your system, you will need to tell CMake where to find qmake:

cmake -DQT_QMAKE_EXECUTABLE:FILEPATH=/usr/something/qmake  ..

Build the project:

make

and run it:

./RenderWindowUISingleInheritance

WINDOWS USERS

Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time. You may also need to add a Qt related path.