[vtkusers] wxVTKRenderWindowInteractor use question

Dean Inglis dean.inglis at camris.ca
Wed Apr 27 09:41:46 EDT 2011


I found the problem solution described here:

http://www.vtk.org/pipermail/vtkusers/2007-April/090723.html

I was using a vtkAxesActor and vtkOrientationMarkerWidget
without a 'self'.  Here's a short working script that shows two windows
(I want to be able to layout multiple frames with wxVTKRWI in a wxPython 
app)

Dean

#!/usr/bin/env python

import wx
import vtk
from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor

class MyFrame(wx.Frame):

    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,
                          size=wx.Size(400,400))

        self.widget = wxVTKRenderWindowInteractor(self, -1)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.widget, 1, wx.EXPAND)
        self.SetSizer(self.sizer)
        self.Layout()

        self.widget.Enable(1)
        self.widget.AddObserver("ExitEvent", lambda o,e,f=self: f.Close())

        ren = vtk.vtkRenderer()
        self.widget.GetRenderWindow().AddRenderer(ren)

        cone = vtk.vtkConeSource()
        cone.SetResolution(8)

        coneMapper = vtk.vtkPolyDataMapper()
        coneMapper.SetInput(cone.GetOutput())

        coneActor = vtk.vtkActor()
        coneActor.SetMapper(coneMapper)

        ren.AddActor(coneActor)

        axes = vtk.vtkAxesActor()
        self.marker = vtk.vtkOrientationMarkerWidget()
        self.marker.SetInteractor( self.widget._Iren )
        self.marker.SetOrientationMarker( axes )
        self.marker.SetViewport(0.75,0,1,0.25)
        self.marker.SetEnabled(1)

        ren.ResetCamera()
        ren.ResetCameraClippingRange()
        cam = ren.GetActiveCamera()
        cam.Elevation(10)
        cam.Azimuth(70)

# every wx app needs an app

class App(wx.App):

    def OnInit(self):
        self.frame1 = MyFrame(None,'test1')
        self.frame1.Show()
        self.frame2 = MyFrame(None,'test2')
        self.frame2.Show()
        return True

if __name__ == '__main__':
    app = App(0)
    app.MainLoop()




> not sure if Im phrasing this correctly but I am
> trying to subclass a wx.Frame and during its initialization,
> set up a wxVTKRenderWindowInteractor.  In the
> example code that appends the file
> VTK/Wrapping/Python/vtk/wx/wxVTKRenderWindowInteractor.py
> an application instance must first be created:
> <snip>
> import wx
> import vtk
> from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
>
> #--------------------------------------------------------------------
> def simpleExample():
>    """Like it says, just a simple example
>    """
>    # every wx app needs an app
>    app = wx.PySimpleApp()
>
>    # create the top-level frame, sizer and wxVTKRWI
>    frame = wx.Frame(None, -1, "wxVTKRenderWindowInteractor", 
> size=(400,400))
>    widget = wxVTKRenderWindowInteractor(frame, -1)
>    sizer = wx.BoxSizer(wx.VERTICAL)
>    sizer.Add(widget, 1, wx.EXPAND)
>    frame.SetSizer(sizer)
>    frame.Layout()
>
>    # It would be more correct (API-wise) to call widget.Initialize() and
>    # widget.Start() here, but Initialize() calls RenderWindow.Render().
>    # That Render() call will get through before we can setup the
>    # RenderWindow() to render via the wxWidgets-created context; this
>    # causes flashing on some platforms and downright breaks things on
>    # other platforms.  Instead, we call widget.Enable().  This means
>    # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
>    # that doesn't matter.
>    widget.Enable(1)
>
>    widget.AddObserver("ExitEvent", lambda o,e,f=frame: f.Close())
>
>    ren = vtk.vtkRenderer()
>    widget.GetRenderWindow().AddRenderer(ren)
>
> # later on in the code the app main loop is activated
> <snip>
>
> but I would like to do something like the following:
>
>
> <snip>
> import wx
> import vtk
> from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
>
> class MyFrame(wx.Frame):
>
>    def __init__(self, parent, title):
>        wx.Frame.__init__(self, parent, -1, title,
>                          size=wx.Size(400,400))
>
>        # create the top-level frame, sizer and wxVTKRWI
>        widget = wxVTKRenderWindowInteractor(self, -1)        sizer = 
> wx.BoxSizer(wx.VERTICAL)
>        sizer.Add(widget, 1, wx.EXPAND)
>        self.SetSizer(sizer)
>        self.Layout()
>
>    # It would be more correct (API-wise) to call widget.Initialize() and
>    # widget.Start() here, but Initialize() calls RenderWindow.Render().
>    # That Render() call will get through before we can setup the
>    # RenderWindow() to render via the wxWidgets-created context; this
>    # causes flashing on some platforms and downright breaks things on
>    # other platforms.  Instead, we call widget.Enable().  This means
>    # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
>    # that doesn't matter.
>        widget.Enable(1)
>
>        widget.AddObserver("ExitEvent", lambda o,e,f=self: f.Close())
>
>        ren = vtk.vtkRenderer()
>        widget.GetRenderWindow().AddRenderer(ren)
> <snip>
>
> and subclass the application so that in its OnInit method
> instantiates the subclassed frame with the vtkRWI:
>
>
> class App(wx.App):
>
>    def OnInit(self):
>        self.frame = MyFrame(None,'test')
>        self.frame.Show()
>        return True
>
> if __name__ == '__main__':
>    app = App(0)
>    app.MainLoop()
>
>
> however, if I run the example with the latter code, as soon as the
> mouse is over the render window, the app crashes. Why in the first case
> does an application have to be created first (according to the 
> documentation in
> vtkRWI it does), while in the second case it appears that this is not 
> possible
> using a subclassed wx.App?
>
> Dean 




More information about the vtkusers mailing list