123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- """
- A fully functional VTK widget for tkinter that uses
- vtkGenericRenderWindowInteractor. The widget is called
- vtkTkRenderWindowInteractor. The initialization part of this code is
- similar to that of the vtkTkRenderWidget.
- Created by Prabhu Ramachandran, April 2002
- """
- from __future__ import absolute_import
- import math, os, sys
- from vtkmodules.vtkRenderingCore import vtkRenderWindow
- from vtkmodules.vtkRenderingUI import vtkGenericRenderWindowInteractor
- if sys.hexversion < 0x03000000:
- # for Python2
- import Tkinter as tkinter
- else:
- # for Python3
- import tkinter
- from .vtkLoadPythonTkWidgets import vtkLoadPythonTkWidgets
- class vtkTkRenderWindowInteractor(tkinter.Widget):
- """ A vtkTkRenderWidndowInteractor for Python.
- Use GetRenderWindow() to get the vtkRenderWindow.
- Create with the keyword stereo=1 in order to generate a
- stereo-capable window.
- Create with the keyword focus_on_enter=1 to enable
- focus-follows-mouse. The default is for a click-to-focus mode.
- __getattr__ is used to make the widget also behave like a
- vtkGenericRenderWindowInteractor.
- """
- def __init__(self, master, cnf={}, **kw):
- """
- Constructor.
- Keyword arguments:
- rw -- Use passed render window instead of creating a new one.
- stereo -- If True, generate a stereo-capable window.
- Defaults to False.
- focus_on_enter -- If True, use a focus-follows-mouse mode.
- Defaults to False where the widget will use a click-to-focus
- mode.
- """
- # load the necessary extensions into tk
- vtkLoadPythonTkWidgets(master.tk)
- try: # check to see if a render window was specified
- renderWindow = kw['rw']
- except KeyError:
- renderWindow = vtkRenderWindow()
- try: # was a stereo rendering context requested?
- if kw['stereo']:
- renderWindow.StereoCapableWindowOn()
- del kw['stereo']
- except KeyError:
- pass
- # check if focus should follow mouse
- if kw.get('focus_on_enter'):
- self._FocusOnEnter = 1
- del kw['focus_on_enter']
- else:
- self._FocusOnEnter = 0
- kw['rw'] = renderWindow.GetAddressAsString("vtkRenderWindow")
- tkinter.Widget.__init__(self, master, 'vtkTkRenderWidget', cnf, kw)
- self._Iren = vtkGenericRenderWindowInteractor()
- self._Iren.SetRenderWindow(self._RenderWindow)
- self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer)
- self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer)
- self._OldFocus = None
- # private attributes
- self.__InExpose = 0
- # create the Tk bindings
- self.BindEvents()
- #self.tk_focusFollowsMouse()
- def __getattr__(self, attr):
- # because the tk part of vtkTkRenderWidget must have
- # the only remaining reference to the RenderWindow when
- # it is destroyed, we can't actually store the RenderWindow
- # as an attribute but instead have to get it from the tk-side
- if attr == '__vtk__':
- return lambda t=self._Iren: t
- elif attr == '_RenderWindow':
- return self.GetRenderWindow()
- elif hasattr(self._Iren, attr):
- return getattr(self._Iren, attr)
- else:
- raise AttributeError(self.__class__.__name__ +
- " has no attribute named " + attr)
- def BindEvents(self):
- """ Bind all the events. """
- self.bind("<Motion>",
- lambda e, s=self: s.MouseMoveEvent(e, 0, 0))
- self.bind("<Control-Motion>",
- lambda e, s=self: s.MouseMoveEvent(e, 1, 0))
- self.bind("<Shift-Motion>",
- lambda e, s=self: s.MouseMoveEvent(e, 1, 1))
- self.bind("<Control-Shift-Motion>",
- lambda e, s=self: s.MouseMoveEvent(e, 0, 1))
- # Left Button
- self.bind("<ButtonPress-1>",
- lambda e, s=self: s.LeftButtonPressEvent(e, 0, 0))
- self.bind("<Control-ButtonPress-1>",
- lambda e, s=self: s.LeftButtonPressEvent(e, 1, 0))
- self.bind("<Shift-ButtonPress-1>",
- lambda e, s=self: s.LeftButtonPressEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonPress-1>",
- lambda e, s=self: s.LeftButtonPressEvent(e, 1, 1))
- self.bind("<ButtonRelease-1>",
- lambda e, s=self: s.LeftButtonReleaseEvent(e, 0, 0))
- self.bind("<Control-ButtonRelease-1>",
- lambda e, s=self: s.LeftButtonReleaseEvent(e, 1, 0))
- self.bind("<Shift-ButtonRelease-1>",
- lambda e, s=self: s.LeftButtonReleaseEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonRelease-1>",
- lambda e, s=self: s.LeftButtonReleaseEvent(e, 1, 1))
- # Middle Button
- self.bind("<ButtonPress-2>",
- lambda e, s=self: s.MiddleButtonPressEvent(e, 0, 0))
- self.bind("<Control-ButtonPress-2>",
- lambda e, s=self: s.MiddleButtonPressEvent(e, 1, 0))
- self.bind("<Shift-ButtonPress-2>",
- lambda e, s=self: s.MiddleButtonPressEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonPress-2>",
- lambda e, s=self: s.MiddleButtonPressEvent(e, 1, 1))
- self.bind("<ButtonRelease-2>",
- lambda e, s=self: s.MiddleButtonReleaseEvent(e, 0, 0))
- self.bind("<Control-ButtonRelease-2>",
- lambda e, s=self: s.MiddleButtonReleaseEvent(e, 1, 0))
- self.bind("<Shift-ButtonRelease-2>",
- lambda e, s=self: s.MiddleButtonReleaseEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonRelease-2>",
- lambda e, s=self: s.MiddleButtonReleaseEvent(e, 1, 1))
- # Right Button
- self.bind("<ButtonPress-3>",
- lambda e, s=self: s.RightButtonPressEvent(e, 0, 0))
- self.bind("<Control-ButtonPress-3>",
- lambda e, s=self: s.RightButtonPressEvent(e, 1, 0))
- self.bind("<Shift-ButtonPress-3>",
- lambda e, s=self: s.RightButtonPressEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonPress-3>",
- lambda e, s=self: s.RightButtonPressEvent(e, 1, 1))
- self.bind("<ButtonRelease-3>",
- lambda e, s=self: s.RightButtonReleaseEvent(e, 0, 0))
- self.bind("<Control-ButtonRelease-3>",
- lambda e, s=self: s.RightButtonReleaseEvent(e, 1, 0))
- self.bind("<Shift-ButtonRelease-3>",
- lambda e, s=self: s.RightButtonReleaseEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonRelease-3>",
- lambda e, s=self: s.RightButtonReleaseEvent(e, 1, 1))
- if sys.platform == 'win32':
- self.bind("<MouseWheel>",
- lambda e, s=self: s.MouseWheelEvent(e, 0, 0))
- self.bind("<Control-MouseWheel>",
- lambda e, s=self: s.MouseWheelEvent(e, 1, 0))
- self.bind("<Shift-MouseWheel>",
- lambda e, s=self: s.MouseWheelEvent(e, 0, 1))
- self.bind("<Control-Shift-MouseWheel>",
- lambda e, s=self: s.MouseWheelEvent(e, 1, 1))
- else:
- # Mouse wheel forward event
- self.bind("<ButtonPress-4>",
- lambda e, s=self: s.MouseWheelForwardEvent(e, 0, 0))
- self.bind("<Control-ButtonPress-4>",
- lambda e, s=self: s.MouseWheelForwardEvent(e, 1, 0))
- self.bind("<Shift-ButtonPress-4>",
- lambda e, s=self: s.MouseWheelForwardEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonPress-4>",
- lambda e, s=self: s.MouseWheelForwardEvent(e, 1, 1))
- # Mouse wheel backward event
- self.bind("<ButtonPress-5>",
- lambda e, s=self: s.MouseWheelBackwardEvent(e, 0, 0))
- self.bind("<Control-ButtonPress-5>",
- lambda e, s=self: s.MouseWheelBackwardEvent(e, 1, 0))
- self.bind("<Shift-ButtonPress-5>",
- lambda e, s=self: s.MouseWheelBackwardEvent(e, 0, 1))
- self.bind("<Control-Shift-ButtonPress-5>",
- lambda e, s=self: s.MouseWheelBackwardEvent(e, 1, 1))
- # Key related events
- self.bind("<KeyPress>",
- lambda e, s=self: s.KeyPressEvent(e, 0, 0))
- self.bind("<Control-KeyPress>",
- lambda e, s=self: s.KeyPressEvent(e, 1, 0))
- self.bind("<Shift-KeyPress>",
- lambda e, s=self: s.KeyPressEvent(e, 0, 1))
- self.bind("<Control-Shift-KeyPress>",
- lambda e, s=self: s.KeyPressEvent(e, 1, 1))
- self.bind("<KeyRelease>",
- lambda e, s=self: s.KeyReleaseEvent(e, 0, 0))
- self.bind("<Control-KeyRelease>",
- lambda e, s=self: s.KeyReleaseEvent(e, 1, 0))
- self.bind("<Shift-KeyRelease>",
- lambda e, s=self: s.KeyReleaseEvent(e, 0, 1))
- self.bind("<Control-Shift-KeyRelease>",
- lambda e, s=self: s.KeyReleaseEvent(e, 1, 1))
- self.bind("<Enter>",
- lambda e, s=self: s.EnterEvent(e, 0, 0))
- self.bind("<Control-Enter>",
- lambda e, s=self: s.EnterEvent(e, 1, 0))
- self.bind("<Shift-Enter>",
- lambda e, s=self: s.EnterEvent(e, 0, 1))
- self.bind("<Control-Shift-Enter>",
- lambda e, s=self: s.EnterEvent(e, 1, 1))
- self.bind("<Leave>",
- lambda e, s=self: s.LeaveEvent(e, 0, 0))
- self.bind("<Control-Leave>",
- lambda e, s=self: s.LeaveEvent(e, 1, 0))
- self.bind("<Shift-Leave>",
- lambda e, s=self: s.LeaveEvent(e, 0, 1))
- self.bind("<Control-Shift-Leave>",
- lambda e, s=self: s.LeaveEvent(e, 1, 1))
- self.bind("<Configure>", self.ConfigureEvent)
- self.bind("<Expose>",lambda e,s=self: s.ExposeEvent())
- def CreateTimer(self, obj, evt):
- self.after(10, self._Iren.TimerEvent)
- def DestroyTimer(self, obj, event):
- """The timer is a one shot timer so will expire automatically."""
- return 1
- def _GrabFocus(self, enter=0):
- self._OldFocus=self.focus_get()
- self.focus()
- def MouseMoveEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.MouseMoveEvent()
- def LeftButtonPressEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.LeftButtonPressEvent()
- if not self._FocusOnEnter:
- self._GrabFocus()
- def LeftButtonReleaseEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.LeftButtonReleaseEvent()
- def MiddleButtonPressEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.MiddleButtonPressEvent()
- if not self._FocusOnEnter:
- self._GrabFocus()
- def MiddleButtonReleaseEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.MiddleButtonReleaseEvent()
- def RightButtonPressEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.RightButtonPressEvent()
- if not self._FocusOnEnter:
- self._GrabFocus()
- def RightButtonReleaseEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.RightButtonReleaseEvent()
- def MouseWheelEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- if event.delta > 0:
- self._Iren.MouseWheelForwardEvent()
- else:
- self._Iren.MouseWheelBackwardEvent()
- def MouseWheelForwardEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.MouseWheelForwardEvent()
- def MouseWheelBackwardEvent(self, event, ctrl, shift):
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, chr(0), 0, None)
- self._Iren.MouseWheelBackwardEvent()
- def KeyPressEvent(self, event, ctrl, shift):
- key = chr(0)
- if event.keysym_num < 256:
- key = chr(event.keysym_num)
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, key, 0, event.keysym)
- self._Iren.KeyPressEvent()
- self._Iren.CharEvent()
- def KeyReleaseEvent(self, event, ctrl, shift):
- key = chr(0)
- if event.keysym_num < 256:
- key = chr(event.keysym_num)
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl,
- shift, key, 0, event.keysym)
- self._Iren.KeyReleaseEvent()
- def ConfigureEvent(self, event):
- self._Iren.SetSize(event.width, event.height)
- self._Iren.ConfigureEvent()
- def EnterEvent(self, event, ctrl, shift):
- if self._FocusOnEnter:
- self._GrabFocus()
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, shift,
- chr(0), 0, None)
- self._Iren.EnterEvent()
- def LeaveEvent(self, event, ctrl, shift):
- if self._FocusOnEnter and (self._OldFocus != None):
- self._OldFocus.focus()
- self._Iren.SetEventInformationFlipY(event.x, event.y, ctrl, shift,
- chr(0), 0, None)
- self._Iren.LeaveEvent()
- def ExposeEvent(self):
- if (not self.__InExpose):
- self.__InExpose = 1
- if (not self._RenderWindow.IsA('vtkCocoaRenderWindow')):
- self.update()
- self._RenderWindow.Render()
- self.__InExpose = 0
- def GetRenderWindow(self):
- addr = self.tk.call(self._w, 'GetRenderWindow')[5:]
- return vtkRenderWindow('_%s_vtkRenderWindow_p' % addr)
- def Render(self):
- self._RenderWindow.Render()
- #----------------------------------------------------------------------------
- def vtkRenderWindowInteractorConeExample():
- """Like it says, just a simple example
- """
- from vtkmodules.vtkFiltersSources import vtkConeSource
- from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer
- # load implementations for rendering and interaction factory classes
- import vtkmodules.vtkRenderingOpenGL2
- import vtkmodules.vtkInteractionStyle
- # create root window
- root = tkinter.Tk()
- # create vtkTkRenderWidget
- pane = vtkTkRenderWindowInteractor(root, width=300, height=300)
- pane.Initialize()
- def quit(obj=root):
- obj.quit()
- pane.AddObserver("ExitEvent", lambda o,e,q=quit: q())
- ren = vtkRenderer()
- pane.GetRenderWindow().AddRenderer(ren)
- cone = vtkConeSource()
- cone.SetResolution(8)
- coneMapper = vtkPolyDataMapper()
- coneMapper.SetInputConnection(cone.GetOutputPort())
- coneActor = vtkActor()
- coneActor.SetMapper(coneMapper)
- ren.AddActor(coneActor)
- # pack the pane into the tk root
- pane.pack(fill='both', expand=1)
- pane.Start()
- # start the tk mainloop
- root.mainloop()
- if __name__ == "__main__":
- vtkRenderWindowInteractorConeExample()
|