GtkGLExtVTKRenderWindowInteractor.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. """
  2. Description:
  3. Provides a pyGtk vtkRenderWindowInteractor widget. This embeds a
  4. vtkRenderWindow inside a GTK widget and uses the
  5. vtkGenericRenderWindowInteractor for the event handling. This is
  6. similar to GtkVTKRenderWindowInteractor.py.
  7. The extensions here allow the use of gtkglext rather than gtkgl and
  8. pygtk-2 rather than pygtk-0. It requires pygtk-2.0.0 or later.
  9. There is a working example at the bottom.
  10. Credits:
  11. John Hunter <jdhunter@ace.bsd.uchicago.edu> developed and tested
  12. this code based on VTK's GtkVTKRenderWindow.py and extended it to
  13. work with pygtk-2.0.0.
  14. License:
  15. VTK license.
  16. """
  17. import sys
  18. import pygtk
  19. pygtk.require('2.0')
  20. import gtk
  21. from gtk import gdk
  22. import gtk.gtkgl
  23. from vtkmodules.vtkRenderingCore import vtkRenderWindow
  24. from vtkmodules.vtkRenderingUI import vtkGenericRenderWindowInteractor
  25. class GtkGLExtVTKRenderWindowInteractor(gtk.gtkgl.DrawingArea):
  26. """ Embeds a vtkRenderWindow into a pyGTK widget and uses
  27. vtkGenericRenderWindowInteractor for the event handling. This
  28. class embeds the RenderWindow correctly. A __getattr__ hook is
  29. provided that makes the class behave like a
  30. vtkGenericRenderWindowInteractor."""
  31. def __init__(self, *args):
  32. gtk.gtkgl.DrawingArea.__init__(self)
  33. self.set_double_buffered(gtk.FALSE)
  34. self._RenderWindow = vtkRenderWindow()
  35. # private attributes
  36. self.__Created = 0
  37. self._ActiveButton = 0
  38. self._Iren = vtkGenericRenderWindowInteractor()
  39. self._Iren.SetRenderWindow(self._RenderWindow)
  40. self._Iren.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
  41. self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer)
  42. self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer)
  43. self.ConnectSignals()
  44. # need this to be able to handle key_press events.
  45. self.set_flags(gtk.CAN_FOCUS)
  46. def set_size_request(self, w, h):
  47. gtk.gtkgl.DrawingArea.set_size_request(self, w, h)
  48. self._RenderWindow.SetSize(w, h)
  49. self._Iren.SetSize(w, h)
  50. self._Iren.ConfigureEvent()
  51. def ConnectSignals(self):
  52. self.connect("realize", self.OnRealize)
  53. self.connect("expose_event", self.OnExpose)
  54. self.connect("configure_event", self.OnConfigure)
  55. self.connect("button_press_event", self.OnButtonDown)
  56. self.connect("button_release_event", self.OnButtonUp)
  57. self.connect("motion_notify_event", self.OnMouseMove)
  58. self.connect("enter_notify_event", self.OnEnter)
  59. self.connect("leave_notify_event", self.OnLeave)
  60. self.connect("key_press_event", self.OnKeyPress)
  61. self.connect("delete_event", self.OnDestroy)
  62. self.add_events(gdk.EXPOSURE_MASK| gdk.BUTTON_PRESS_MASK |
  63. gdk.BUTTON_RELEASE_MASK |
  64. gdk.KEY_PRESS_MASK |
  65. gdk.POINTER_MOTION_MASK |
  66. gdk.POINTER_MOTION_HINT_MASK |
  67. gdk.ENTER_NOTIFY_MASK | gdk.LEAVE_NOTIFY_MASK)
  68. def __getattr__(self, attr):
  69. """Makes the object behave like a
  70. vtkGenericRenderWindowInteractor"""
  71. if attr == '__vtk__':
  72. return lambda t=self._Iren: t
  73. elif hasattr(self._Iren, attr):
  74. return getattr(self._Iren, attr)
  75. else:
  76. raise AttributeError(self.__class__.__name__ +
  77. " has no attribute named " + attr)
  78. def CreateTimer(self, obj, event):
  79. gtk.timeout_add(10, self._Iren.TimerEvent)
  80. def DestroyTimer(self, obj, event):
  81. """The timer is a one shot timer so will expire automatically."""
  82. return 1
  83. def GetRenderWindow(self):
  84. return self._RenderWindow
  85. def Render(self):
  86. if self.__Created:
  87. self._RenderWindow.Render()
  88. def OnRealize(self, *args):
  89. if self.__Created == 0:
  90. # you can't get the xid without the window being realized.
  91. self.realize()
  92. if sys.platform=='win32':
  93. win_id = str(self.widget.window.handle)
  94. else:
  95. win_id = str(self.widget.window.xid)
  96. self._RenderWindow.SetWindowInfo(win_id)
  97. #self._Iren.Initialize()
  98. self.__Created = 1
  99. return gtk.TRUE
  100. def OnConfigure(self, widget, event):
  101. self.widget=widget
  102. self._Iren.SetSize(event.width, event.height)
  103. self._Iren.ConfigureEvent()
  104. self.Render()
  105. return gtk.TRUE
  106. def OnExpose(self, *args):
  107. self.Render()
  108. return gtk.TRUE
  109. def OnDestroy(self, event=None):
  110. self.hide()
  111. del self._RenderWindow
  112. self.destroy()
  113. return gtk.TRUE
  114. def _GetCtrlShift(self, event):
  115. ctrl, shift = 0, 0
  116. if ((event.state & gdk.CONTROL_MASK) == gdk.CONTROL_MASK):
  117. ctrl = 1
  118. if ((event.state & gdk.SHIFT_MASK) == gdk.SHIFT_MASK):
  119. shift = 1
  120. return ctrl, shift
  121. def OnButtonDown(self, wid, event):
  122. """Mouse button pressed."""
  123. m = self.get_pointer()
  124. ctrl, shift = self._GetCtrlShift(event)
  125. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  126. chr(0), 0, None)
  127. button = event.button
  128. if button == 3:
  129. self._Iren.RightButtonPressEvent()
  130. return gtk.TRUE
  131. elif button == 1:
  132. self._Iren.LeftButtonPressEvent()
  133. return gtk.TRUE
  134. elif button == 2:
  135. self._Iren.MiddleButtonPressEvent()
  136. return gtk.TRUE
  137. else:
  138. return gtk.FALSE
  139. def OnButtonUp(self, wid, event):
  140. """Mouse button released."""
  141. m = self.get_pointer()
  142. ctrl, shift = self._GetCtrlShift(event)
  143. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  144. chr(0), 0, None)
  145. button = event.button
  146. if button == 3:
  147. self._Iren.RightButtonReleaseEvent()
  148. return gtk.TRUE
  149. elif button == 1:
  150. self._Iren.LeftButtonReleaseEvent()
  151. return gtk.TRUE
  152. elif button == 2:
  153. self._Iren.MiddleButtonReleaseEvent()
  154. return gtk.TRUE
  155. return gtk.FALSE
  156. def OnMouseMove(self, wid, event):
  157. """Mouse has moved."""
  158. m = self.get_pointer()
  159. ctrl, shift = self._GetCtrlShift(event)
  160. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  161. chr(0), 0, None)
  162. self._Iren.MouseMoveEvent()
  163. return gtk.TRUE
  164. def OnEnter(self, wid, event):
  165. """Entering the vtkRenderWindow."""
  166. self.grab_focus()
  167. m = self.get_pointer()
  168. ctrl, shift = self._GetCtrlShift(event)
  169. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  170. chr(0), 0, None)
  171. self._Iren.EnterEvent()
  172. return gtk.TRUE
  173. def OnLeave(self, wid, event):
  174. """Leaving the vtkRenderWindow."""
  175. m = self.get_pointer()
  176. ctrl, shift = self._GetCtrlShift(event)
  177. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  178. chr(0), 0, None)
  179. self._Iren.LeaveEvent()
  180. return gtk.TRUE
  181. def OnKeyPress(self, wid, event):
  182. """Key pressed."""
  183. m = self.get_pointer()
  184. ctrl, shift = self._GetCtrlShift(event)
  185. keycode, keysym = event.keyval, event.string
  186. key = chr(0)
  187. if keycode < 256:
  188. key = chr(keycode)
  189. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  190. key, 0, keysym)
  191. self._Iren.KeyPressEvent()
  192. self._Iren.CharEvent()
  193. return gtk.TRUE
  194. def OnKeyRelease(self, wid, event):
  195. "Key released."
  196. m = self.get_pointer()
  197. ctrl, shift = self._GetCtrlShift(event)
  198. keycode, keysym = event.keyval, event.string
  199. key = chr(0)
  200. if keycode < 256:
  201. key = chr(keycode)
  202. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  203. key, 0, keysym)
  204. self._Iren.KeyReleaseEvent()
  205. return gtk.TRUE
  206. def Initialize(self):
  207. if self.__Created:
  208. self._Iren.Initialize()
  209. def SetPicker(self, picker):
  210. self._Iren.SetPicker(picker)
  211. def GetPicker(self, picker):
  212. return self._Iren.GetPicker()
  213. def main():
  214. from vtkmodules.vtkFiltersSources import vtkConeSource
  215. from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer
  216. # load implementations for rendering and interaction factory classes
  217. import vtkmodules.vtkRenderingOpenGL2
  218. import vtkmodules.vtkInteractionStyle
  219. # The main window
  220. window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  221. window.set_title("A GtkVTKRenderWindow Demo!")
  222. window.connect("destroy", gtk.mainquit)
  223. window.connect("delete_event", gtk.mainquit)
  224. window.set_border_width(10)
  225. # A VBox into which widgets are packed.
  226. vbox = gtk.VBox(spacing=3)
  227. window.add(vbox)
  228. vbox.show()
  229. # The GtkVTKRenderWindow
  230. gvtk = GtkGLExtVTKRenderWindowInteractor()
  231. #gvtk.SetDesiredUpdateRate(1000)
  232. gvtk.set_size_request(400, 400)
  233. vbox.pack_start(gvtk)
  234. gvtk.show()
  235. gvtk.Initialize()
  236. gvtk.Start()
  237. # prevents 'q' from exiting the app.
  238. gvtk.AddObserver("ExitEvent", lambda o,e,x=None: x)
  239. # The VTK stuff.
  240. cone = vtkConeSource()
  241. cone.SetResolution(80)
  242. coneMapper = vtkPolyDataMapper()
  243. coneMapper.SetInputConnection(cone.GetOutputPort())
  244. #coneActor = vtkLODActor()
  245. coneActor = vtkActor()
  246. coneActor.SetMapper(coneMapper)
  247. coneActor.GetProperty().SetColor(0.5, 0.5, 1.0)
  248. ren = vtkRenderer()
  249. gvtk.GetRenderWindow().AddRenderer(ren)
  250. ren.AddActor(coneActor)
  251. # A simple quit button
  252. quit = gtk.Button("Quit!")
  253. quit.connect("clicked", gtk.mainquit)
  254. vbox.pack_start(quit)
  255. quit.show()
  256. # show the main window and start event processing.
  257. window.show()
  258. gtk.mainloop()
  259. if __name__ == "__main__":
  260. main()