VTK and Qt

Tom Radcliffe radcliffe at igotechnologies.com
Mon Oct 18 16:05:25 EDT 1999


A while back I posted a possible method for using VTK and Qt
together that is really simple -- a modified example is
attached.  I've looked at this fairly carefully now and
concluded it is not a hack, but a legitimate means of tieing
these two beautiful frameworks together.

There is a small problem, however.  It turns out that if you
try this under Windows you get the error message:
"SetPixelFormat failed" and the application exits.  This can
be fixed by changing the lines (around line 335 in VTK 2.4)
in vtkWin32OpenGLRenderWindow:

if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) {
       int err = GetLastError();
        MessageBox(WindowFromDC(hDC), SetPixelFormat
failed",
"Error", MB_ICONERROR | MB_OK);
        exit(1);
}

to something like:

if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) {
   vtkGenericWarningMacro("SetPixelFormat failed!");
}

This would still allow real problems to be detected while
debugging, but would prevent doing a hard fail on what ought
to be a benign error most of the time.  According to the
Windows docs, SetPixelFormat will always fail after the
first call, so if VTK is being used with any other toolkit
or library that calls SetPixelFormat before VTK does, the
application will exit even though the error is benign.  

I would like to be able to put a condition on the value
returned by GetLastError, but in true Microsoft fashion
there seems to be only one error code used by
SetPixelFormat, and that is ERROR_INVALID_PIXEL_FORMAT,
which is clearly not the problem here because VTK is getting
the pixel format by asking the system for the best format
for the given DC.

Ergo, I request the Keepers of the Code to modify
vtkWin32OpenGLRenderWindow accordingly -- it would make
portable integration of VTK and Qt much easier, and surely
this is a worthy goal.

-- Tom

Tom Radcliffe
Senior Software Designer
iGO Technologies Inc.
radcliffe at igotechnologies.com

===============================================

Here is a modified example of how to integrate VTK and Qt by
using technically non-portable methods in both to pass a
native window ID from Qt to VTK.  Although extremely simple,
this method does not allow interaction via a VTK interactor,
because the Qt window gets all the GUI events.  From my
point of view this is not a bad thing, because I want to use
Qt for interaction, but people who want to use VTK
interactors may not be too happy about it.  

There is an implementation datail of VTK that this depends
on, which is that on rendering, VTK asks the native window
handle what size it is.  This means that VTK deals with
resize events properly by redrawing to the appropriate size,
even though it never actually gets a resize event -- it just
gets a re-render request via the Qt paintGL handler as
shown.

Apart from this detail, which can be easily mocked up in
client code if the VTK implementation ever changes, this
method of VTK/Qt integration is not a hack, and should be
useful whenever native VTK interactors are not required.

================================

#include <qapplication.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qgl.h>

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"

class QGLWindow : public QGLWidget
{
public:
  QGLWindow();

  void setRenderWindow(vtkRenderWindow* pRenderWindow)
        {m_pRenderWindow = pRenderWindow;}
  
protected:
  virtual void paintGL( );
  virtual void initializeGL( );
  virtual void resizeGL( int w, int h );

private:

  bool                  m_bInit;
  vtkRenderWindow*      m_pRenderWindow;

};


QGLWindow::QGLWindow() : m_bInit(true)
{
}

void QGLWindow::initializeGL( )
{
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glColor3f(1.0, 0.0, 0.0);
}

void QGLWindow::resizeGL( int w, int h)
{
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(0.0,w,0.0,h);
  glMatrixMode(GL_MODELVIEW);
  
  updateGL();
}

void QGLWindow::paintGL( )
{
  // Get the native window ID and pass it 
  // to the VTK render window
  // before we render for the first time...
  if (m_bInit)
  {
    WId nId = winId();
    m_pRenderWindow->SetWindowId((void*) nId);
    m_bInit = false;
  }
  else // prevent flashing by no first render
  {
    m_pRenderWindow->Render();
  }
}

int main( int argc, char* argv[] )
{
  QApplication::setColorSpec(QApplication::CustomColor);
  QApplication myapp( argc, argv );

  QGLWindow* mywidget = new QGLWindow();
  mywidget->resize( 400, 400 );
  
  myapp.setMainWidget( mywidget );
  
  // Set up the vtk stuff...

  // create a rendering window and renderer
  vtkRenderer *ren = vtkRenderer::New();

  vtkRenderWindow *renWindow = vtkRenderWindow::New();
  renWindow->AddRenderer(ren);

  // tell widget about window
  mywidget->setRenderWindow(renWindow); 

  // create an actor and give it cone geometry
  vtkConeSource *cone = vtkConeSource::New();
  cone->SetResolution(8);
  vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
  coneMapper->SetInput(cone->GetOutput());
  vtkActor *coneActor = vtkActor::New();
  coneActor->SetMapper(coneMapper);

  // assign our actor to the renderer
  ren->AddActor(coneActor);

  mywidget->show();

  // let Qt do the interaction -- vtk is a passenger
  int nReturn = myapp.exec();

  // Clean vtk stuff
  ren->Delete();
  renWindow->Delete();

  cone->Delete();
  coneMapper->Delete();
  coneActor->Delete();

  return nReturn;
}


-----------------------------------------------------------------------------
This is the private VTK discussion list.  Please keep messages on-topic.
Check the FAQ at: <http://www.automatrix.com/cgi-bin/vtkfaq>
To UNSUBSCRIBE, send message body containing "unsubscribe vtkusers" to
<majordomo at gsao.med.ge.com>.  For help, send message body containing
"info vtkusers" to the same address.     Live long and prosper.
-----------------------------------------------------------------------------




More information about the vtkusers mailing list