GtkVTKRenderWindowInteractor.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. based on vtkTkRenderWindow.py.
  7. The class uses the gtkgl.GtkGLArea widget (gtkglarea). This avoids
  8. a lot of problems with flicker.
  9. There is a working example at the bottom.
  10. Created by Prabhu Ramachandran, April 2002.
  11. Bugs:
  12. (*) There is a focus related problem. Tkinter has a focus object
  13. that handles focus events. I don't know of an equivalent object
  14. under GTK. So, when an 'enter_notify_event' is received on the
  15. GtkVTKRenderWindow I grab the focus but I don't know what to do when
  16. I get a 'leave_notify_event'.
  17. (*) Will not work under Win32 because it uses the XID of a window in
  18. OnRealize. Suggestions to fix this will be appreciated.
  19. """
  20. import gtk, GDK, gtkgl
  21. from vtkmodules.vtkRenderingUI import vtkGenericRenderWindowInteractor
  22. import math
  23. class GtkVTKRenderWindowInteractor(gtkgl.GtkGLArea):
  24. """ Embeds a vtkRenderWindow into a pyGTK widget and uses
  25. vtkGenericRenderWindowInteractor for the event handling. This
  26. class embeds the RenderWindow correctly. A __getattr__ hook is
  27. provided that makes the class behave like a
  28. vtkGenericRenderWindowInteractor."""
  29. def __init__(self, *args):
  30. l = list(args)
  31. attr = (gtkgl.RGBA, gtkgl.DOUBLEBUFFER)
  32. l.insert(0, self)
  33. l.insert(1, attr)
  34. apply(gtkgl.GtkGLArea.__init__, l)
  35. self._RenderWindow = vtkRenderWindow()
  36. # private attributes
  37. self.__Created = 0
  38. self._ActiveButton = 0
  39. self._Iren = vtkGenericRenderWindowInteractor()
  40. self._Iren.SetRenderWindow(self._RenderWindow)
  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. # default size
  47. self.set_usize(300, 300)
  48. def set_usize(self, w, h):
  49. gtkgl.GtkGLArea.set_usize(self, w, h)
  50. self._RenderWindow.SetSize(w, h)
  51. self._Iren.SetSize(w, h)
  52. self._Iren.ConfigureEvent()
  53. def ConnectSignals(self):
  54. self.connect("realize", self.OnRealize)
  55. self.connect("expose_event", self.OnExpose)
  56. self.connect("configure_event", self.OnConfigure)
  57. self.connect("button_press_event", self.OnButtonDown)
  58. self.connect("button_release_event", self.OnButtonUp)
  59. self.connect("motion_notify_event", self.OnMouseMove)
  60. self.connect("enter_notify_event", self.OnEnter)
  61. self.connect("leave_notify_event", self.OnLeave)
  62. self.connect("key_press_event", self.OnKeyPress)
  63. self.connect("delete_event", self.OnDestroy)
  64. self.add_events(GDK.EXPOSURE_MASK| GDK.BUTTON_PRESS_MASK |
  65. GDK.BUTTON_RELEASE_MASK |
  66. GDK.KEY_PRESS_MASK |
  67. GDK.POINTER_MOTION_MASK |
  68. GDK.POINTER_MOTION_HINT_MASK |
  69. GDK.ENTER_NOTIFY_MASK | GDK.LEAVE_NOTIFY_MASK)
  70. def __getattr__(self, attr):
  71. """Makes the object behave like a
  72. vtkGenericRenderWindowInteractor"""
  73. if attr == '__vtk__':
  74. return lambda t=self._Iren: t
  75. elif hasattr(self._Iren, attr):
  76. return getattr(self._Iren, attr)
  77. else:
  78. raise AttributeError(self.__class__.__name__ +
  79. " has no attribute named " + attr)
  80. def CreateTimer(self, obj, event):
  81. gtk.timeout_add(10, self._Iren.TimerEvent)
  82. def DestroyTimer(self, obj, event):
  83. """The timer is a one shot timer so will expire automatically."""
  84. return 1
  85. def GetRenderWindow(self):
  86. return self._RenderWindow
  87. def Render(self):
  88. if self.__Created:
  89. self._RenderWindow.Render()
  90. def OnRealize(self, *args):
  91. if self.__Created == 0:
  92. # you can't get the xid without the window being realized.
  93. self.realize()
  94. win_id = str(self.get_window().xid)
  95. self._RenderWindow.SetWindowInfo(win_id)
  96. self._Iren.Initialize()
  97. self.__Created = 1
  98. return gtk.TRUE
  99. def OnConfigure(self, wid, event=None):
  100. sz = self._RenderWindow.GetSize()
  101. if (event.width != sz[0]) or (event.height != sz[1]):
  102. self._Iren.SetSize(event.width, event.height)
  103. self._Iren.ConfigureEvent()
  104. return gtk.TRUE
  105. def OnExpose(self, *args):
  106. self.Render()
  107. return gtk.TRUE
  108. def OnDestroy(self, event=None):
  109. self.hide()
  110. del self._RenderWindow
  111. self.destroy()
  112. return gtk.TRUE
  113. def _GetCtrlShift(self, event):
  114. ctrl, shift = 0, 0
  115. if ((event.state & GDK.CONTROL_MASK) == GDK.CONTROL_MASK):
  116. ctrl = 1
  117. if ((event.state & GDK.SHIFT_MASK) == GDK.SHIFT_MASK):
  118. shift = 1
  119. return ctrl, shift
  120. def OnButtonDown(self, wid, event):
  121. """Mouse button pressed."""
  122. m = self.get_pointer()
  123. ctrl, shift = self._GetCtrlShift(event)
  124. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  125. chr(0), 0, None)
  126. button = event.button
  127. if button == 3:
  128. self._Iren.RightButtonPressEvent()
  129. return gtk.TRUE
  130. elif button == 1:
  131. self._Iren.LeftButtonPressEvent()
  132. return gtk.TRUE
  133. elif button == 2:
  134. self._Iren.MiddleButtonPressEvent()
  135. return gtk.TRUE
  136. else:
  137. return gtk.FALSE
  138. def OnButtonUp(self, wid, event):
  139. """Mouse button released."""
  140. m = self.get_pointer()
  141. ctrl, shift = self._GetCtrlShift(event)
  142. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  143. chr(0), 0, None)
  144. button = event.button
  145. if button == 3:
  146. self._Iren.RightButtonReleaseEvent()
  147. return gtk.TRUE
  148. elif button == 1:
  149. self._Iren.LeftButtonReleaseEvent()
  150. return gtk.TRUE
  151. elif button == 2:
  152. self._Iren.MiddleButtonReleaseEvent()
  153. return gtk.TRUE
  154. return gtk.FALSE
  155. def OnMouseMove(self, wid, event):
  156. """Mouse has moved."""
  157. m = self.get_pointer()
  158. ctrl, shift = self._GetCtrlShift(event)
  159. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  160. chr(0), 0, None)
  161. self._Iren.MouseMoveEvent()
  162. return gtk.TRUE
  163. def OnEnter(self, wid, event):
  164. """Entering the vtkRenderWindow."""
  165. self.grab_focus()
  166. m = self.get_pointer()
  167. ctrl, shift = self._GetCtrlShift(event)
  168. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  169. chr(0), 0, None)
  170. self._Iren.EnterEvent()
  171. return gtk.TRUE
  172. def OnLeave(self, wid, event):
  173. """Leaving the vtkRenderWindow."""
  174. m = self.get_pointer()
  175. ctrl, shift = self._GetCtrlShift(event)
  176. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  177. chr(0), 0, None)
  178. self._Iren.LeaveEvent()
  179. return gtk.TRUE
  180. def OnKeyPress(self, wid, event):
  181. """Key pressed."""
  182. m = self.get_pointer()
  183. ctrl, shift = self._GetCtrlShift(event)
  184. keycode, keysym = event.keyval, event.string
  185. key = chr(0)
  186. if keycode < 256:
  187. key = chr(keycode)
  188. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  189. key, 0, keysym)
  190. self._Iren.KeyPressEvent()
  191. self._Iren.CharEvent()
  192. return gtk.TRUE
  193. def OnKeyRelease(self, wid, event):
  194. "Key released."
  195. m = self.get_pointer()
  196. ctrl, shift = self._GetCtrlShift(event)
  197. keycode, keysym = event.keyval, event.string
  198. key = chr(0)
  199. if keycode < 256:
  200. key = chr(keycode)
  201. self._Iren.SetEventInformationFlipY(m[0], m[1], ctrl, shift,
  202. key, 0, keysym)
  203. self._Iren.KeyReleaseEvent()
  204. return gtk.TRUE
  205. def Initialize(self):
  206. if self.__Created:
  207. self._Iren.Initialize()
  208. def main():
  209. from vtkmodules.vtkFiltersSources import vtkConeSource
  210. from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer
  211. # load implementations for rendering and interaction factory classes
  212. import vtkmodules.vtkRenderingOpenGL2
  213. import vtkmodules.vtkInteractionStyle
  214. # The main window
  215. window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
  216. window.set_title("A GtkVTKRenderWindow Demo!")
  217. window.connect("destroy", gtk.mainquit)
  218. window.connect("delete_event", gtk.mainquit)
  219. window.set_border_width(10)
  220. # A VBox into which widgets are packed.
  221. vbox = gtk.GtkVBox(spacing=3)
  222. window.add(vbox)
  223. vbox.show()
  224. # The GtkVTKRenderWindow
  225. gvtk = GtkVTKRenderWindowInteractor()
  226. #gvtk.SetDesiredUpdateRate(1000)
  227. gvtk.set_usize(400, 400)
  228. vbox.pack_start(gvtk)
  229. gvtk.show()
  230. gvtk.Initialize()
  231. gvtk.Start()
  232. # prevents 'q' from exiting the app.
  233. gvtk.AddObserver("ExitEvent", lambda o,e,x=None: x)
  234. # The VTK stuff.
  235. cone = vtkConeSource()
  236. cone.SetResolution(80)
  237. coneMapper = vtkPolyDataMapper()
  238. coneMapper.SetInputConnection(cone.GetOutputPort())
  239. #coneActor = vtkLODActor()
  240. coneActor = vtkActor()
  241. coneActor.SetMapper(coneMapper)
  242. coneActor.GetProperty().SetColor(0.5, 0.5, 1.0)
  243. ren = vtkRenderer()
  244. gvtk.GetRenderWindow().AddRenderer(ren)
  245. ren.AddActor(coneActor)
  246. # A simple quit button
  247. quit = gtk.GtkButton("Quit!")
  248. quit.connect("clicked", gtk.mainquit)
  249. vbox.pack_start(quit)
  250. quit.show()
  251. # show the main window and start event processing.
  252. window.show()
  253. gtk.mainloop()
  254. if __name__ == "__main__":
  255. main()