I have this code that works without Qt:
>> cat testVTKQt.cpp
#include <iostream> // cout, cerr
#include <stdexcept> // exception
#include <thread> // jthread
#include <string> // string
#include <sstream> // stringstream
#include <random> // std::uniform_real_distribution
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkVertexGlyphFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h" // GetProperty
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
void updateData(unsigned int const & size,
vtkNew<vtkPolyData> & data,
vtkSmartPointer<vtkRenderWindow> & rdrWin,
bool const updateRender = true) {
// Create random distribution.
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> distrib(-10000., 10000.);
// Update data with random points.
vtkNew<vtkPoints> points;
data->SetPoints(points);
for (unsigned int i = 0; i < size; i++) {
data->GetPoints()->InsertNextPoint(distrib(gen), distrib(gen), distrib(gen));
}
// Update the scene.
data->Modified();
if (updateRender) {
rdrWin->Render (); // Render an image (lights and cameras are created automatically).
}
}
void createScene(vtkNew<vtkPolyData> & data,
vtkSmartPointer<vtkRenderWindow> & rdrWin) {
// Create a filter.
vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
filter->SetInputData(data);
// Create a mapper.
vtkSmartPointer<vtkPolyDataMapper> map = vtkSmartPointer<vtkPolyDataMapper>::New();
map->SetInputConnection(filter->GetOutputPort()); // Map to graphics library.
// Create an actor.
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(map);
// Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
rdrWin->AddRenderer(rdr);
vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
rdrInt->SetRenderWindow(rdrWin);
rdrInt->Initialize();
// Define the scene to render.
actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
rdr->AddActor(actor); // Add the actor to the scene.
rdr->SetBackground(1, 1, 1); // Background color white.
// Render.
rdrWin->Render (); // Render an image (lights and cameras are created automatically).
rdrInt->Start (); // Hold window and watches for events (keypress, mouse, ...) in the vtkRenderWindow.
}
int main () {
int rc = 1;
try {
// Create point cloud.
vtkSmartPointer<vtkRenderWindow> rdrWin = vtkSmartPointer<vtkRenderWindow>::New(); // Window to render into.
vtkNew<vtkPolyData> data;
updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
std::jthread visu(createScene, std::ref(data), std::ref(rdrWin));
// Modify the scene.
std::cout << "Type a number (integer) as point cloud size..." << std::endl;
while (true) {
// Getting user command.
std::string line;
std::getline(std::cin, line);
// Getting point cloud size.
std::stringstream str;
str << line;
unsigned int size = 0;
str >> size;
if (!str) {
std::cout << "Bad number (not an integer): " << line << std::endl;
continue;
}
// Update point cloud.
std::cout << "Point cloud size: " << size << std::endl;
updateData(size, data, rdrWin);
};
rc = 0;
}
catch(std::exception & e) {
rc = 1;
cerr << "ERROR - " << e.what() << endl;
}
return rc;
}
Now, I have compiled VTK from source with Qt support, and I have tested that <VTK_ROOT>/Examples/GUI/Qt/SimpleView example works OK.
But, when I try to include this VTK code in Qt:
>> git diff
diff --git a/testVTKQt.cpp b/testVTKQt.cpp
index 7e17c1a..ac6cb0a 100644
--- a/testVTKQt.cpp
+++ b/testVTKQt.cpp
@@ -5,6 +5,13 @@
#include <sstream> // stringstream
#include <random> // std::uniform_real_distribution
+//----------Since we're not building with CMake, we need to init the VTK modules------------------
+//--------------linking with the VTK libraries is often not enough--------------------------------
+#include <vtkAutoInit.h>
+VTK_MODULE_INIT(vtkRenderingOpenGL2) // VTK was built with vtkRenderingOpenGL2
+VTK_MODULE_INIT(vtkInteractionStyle)
+VTK_MODULE_INIT(vtkRenderingFreeType)
+// VTK
#include "vtkNew.h"
#include "vtkSmartPointer.h"
#include "vtkPoints.h"
@@ -14,12 +21,17 @@
#include "vtkProperty.h" // GetProperty
#include "vtkActor.h"
#include "vtkRenderer.h"
-#include "vtkRenderWindow.h"
-#include "vtkRenderWindowInteractor.h"
+#include "vtkGenericOpenGLRenderWindow.h"
+//#include "vtkRenderWindowInteractor.h"
+
+// Qt
+#include <QtGui/QSurfaceFormat>
+#include <QtWidgets/QApplication>
+#include "QVTKOpenGLNativeWidget.h"
void updateData(unsigned int const & size,
vtkNew<vtkPolyData> & data,
- vtkSmartPointer<vtkRenderWindow> & rdrWin,
+ vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin,
bool const updateRender = true) {
// Create random distribution.
std::random_device rd;
@@ -40,8 +52,9 @@ void updateData(unsigned int const & size,
}
}
-void createScene(vtkNew<vtkPolyData> & data,
- vtkSmartPointer<vtkRenderWindow> & rdrWin) {
+void createScene(QVTKOpenGLNativeWidget & wdg,
+ vtkNew<vtkPolyData> & data,
+ vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
// Create a filter.
vtkSmartPointer<vtkVertexGlyphFilter> filter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
filter->SetInputData(data);
@@ -55,11 +68,12 @@ void createScene(vtkNew<vtkPolyData> & data,
actor->SetMapper(map);
// Create a renderer and a render window. Renderers and Windows represent the end of the VTK pipeline, which users actually see on the screen.
+ wdg.setRenderWindow(rdrWin);
vtkSmartPointer<vtkRenderer> rdr = vtkSmartPointer<vtkRenderer>::New();
- rdrWin->AddRenderer(rdr);
- vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
- rdrInt->SetRenderWindow(rdrWin);
- rdrInt->Initialize();
+ wdg.renderWindow()->AddRenderer(rdr);
+ //vtkSmartPointer<vtkRenderWindowInteractor> rdrInt = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Watches for events (keypress, mouse, ...).
+ //rdrInt->SetRenderWindow(rdrWin);
+ //rdrInt->Initialize();
// Define the scene to render.
actor->GetProperty()->SetColor(0, 0, 1); // Set sphere color to blue (RGB).
@@ -68,18 +82,32 @@ void createScene(vtkNew<vtkPolyData> & data,
// Render.
rdrWin->Render (); // Render an image (lights and cameras are created automatically).
- rdrInt->Start (); // Hold window and watches for events (keypress, mouse, ...) in the vtkRenderWindow.
+ //rdrInt->Start (); // Hold window and watches for events (keypress, mouse, ...).
+}
+
+void createApplication(int & argc, char** argv,
+ vtkNew<vtkPolyData> & data,
+ vtkSmartPointer<vtkGenericOpenGLRenderWindow> & rdrWin) {
+ // Needed to ensure appropriate OpenGL context is created for VTK rendering.
+ QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
+
+ // Create Qt application.
+ QApplication app(argc, argv);
+ //QVTKRenderWidget wdg;
+ QVTKOpenGLNativeWidget wdg;
+ createScene(wdg, data, rdrWin);
+ app.exec();
}
-int main () {
+int main (int argc, char** argv) {
int rc = 1;
try {
// Create point cloud.
- vtkSmartPointer<vtkRenderWindow> rdrWin = vtkSmartPointer<vtkRenderWindow>::New(); // Window to render into.
+ vtkSmartPointer<vtkGenericOpenGLRenderWindow> rdrWin = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New(); // Window to render into.
vtkNew<vtkPolyData> data;
updateData(100, data, rdrWin, false); // Do NOT render until the thread has not started and set up the scene.
- std::jthread visu(createScene, std::ref(data), std::ref(rdrWin));
+ std::jthread visu(createApplication, std::ref(argc), std::ref(argv), std::ref(data), std::ref(rdrWin));
// Modify the scene.
std::cout << "Type a number (integer) as point cloud size..." << std::endl;
I have :
- replaced vtkRenderWindow with vtkGenericOpenGLRenderWindow
- commented vtkRenderWindowInteractor taht seems to make Qt crash
- created QVTKOpenGLNativeWidget (same problem with QVTKRenderWidget) and QApplication
… But, get no window at run time:
./testVTKQt
does not open / render any window ?!..
did i miss something ?
any help is appreciated!