You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							349 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							349 lines
						
					
					
						
							12 KiB
						
					
					
				| """
 | |
| A simple VTK input file for PyQt, the qt bindings for python.
 | |
| See http://www.trolltech.com for qt documentation, and
 | |
| http://www.river-bank.demon.co.uk or http://www.thekompany.com
 | |
| for the qt python bindings.
 | |
| 
 | |
| This class is based on the vtkGenericRenderWindowInteractor and is
 | |
| therefore fairly powerful.  It should also play nicely with the
 | |
| vtk3DWidget code.
 | |
| 
 | |
| Created by Prabhu Ramachandran, May 2002
 | |
| Based on David Gobbi's QVTKRenderWidget.py
 | |
| 
 | |
| Changes by Gerard Vermeulen Feb. 2003
 | |
|  Win32 support.
 | |
| 
 | |
| Changes by Gerard Vermeulen, May 2003
 | |
|  Bug fixes and better integration with the Qt framework.
 | |
| """
 | |
| 
 | |
| """
 | |
| This class works with the UNIX and Win32 versions of Qt.
 | |
| 
 | |
| Depending on the OpenGL graphics drivers, it may not
 | |
| be possible to have more than one QVTKRenderWidget
 | |
| per application.
 | |
| 
 | |
| In short, this class is experimental.
 | |
| """
 | |
| 
 | |
| 
 | |
| # To do for Win32:
 | |
| # 1. More testing to assure that the widget is always cleaned up
 | |
| #    properly and does not crash the application.
 | |
| 
 | |
| import qt
 | |
| import vtk
 | |
| 
 | |
| class QVTKRenderWindowInteractor(qt.QWidget):
 | |
| 
 | |
|     """ A QVTKRenderWindowInteractor for Python and Qt.  Uses a
 | |
|     vtkGenericRenderWindowInteractor to handle the interactions.  Use
 | |
|     GetRenderWindow() to get the vtkRenderWindow.  Create with the
 | |
|     keyword stereo=1 in order to generate a stereo-capable window.
 | |
| 
 | |
|     The user interface is summarized in vtkInteractorStyle.h:
 | |
| 
 | |
|     - Keypress j / Keypress t: toggle between joystick (position
 | |
|     sensitive) and trackball (motion sensitive) styles. In joystick
 | |
|     style, motion occurs continuously as long as a mouse button is
 | |
|     pressed. In trackball style, motion occurs when the mouse button
 | |
|     is pressed and the mouse pointer moves.
 | |
| 
 | |
|     - Keypress c / Keypress o: toggle between camera and object
 | |
|     (actor) modes. In camera mode, mouse events affect the camera
 | |
|     position and focal point. In object mode, mouse events affect
 | |
|     the actor that is under the mouse pointer.
 | |
| 
 | |
|     - Button 1: rotate the camera around its focal point (if camera
 | |
|     mode) or rotate the actor around its origin (if actor mode). The
 | |
|     rotation is in the direction defined from the center of the
 | |
|     renderer's viewport towards the mouse position. In joystick mode,
 | |
|     the magnitude of the rotation is determined by the distance the
 | |
|     mouse is from the center of the render window.
 | |
| 
 | |
|     - Button 2: pan the camera (if camera mode) or translate the actor
 | |
|     (if object mode). In joystick mode, the direction of pan or
 | |
|     translation is from the center of the viewport towards the mouse
 | |
|     position. In trackball mode, the direction of motion is the
 | |
|     direction the mouse moves. (Note: with 2-button mice, pan is
 | |
|     defined as <Shift>-Button 1.)
 | |
| 
 | |
|     - Button 3: zoom the camera (if camera mode) or scale the actor
 | |
|     (if object mode). Zoom in/increase scale if the mouse position is
 | |
|     in the top half of the viewport; zoom out/decrease scale if the
 | |
|     mouse position is in the bottom half. In joystick mode, the amount
 | |
|     of zoom is controlled by the distance of the mouse pointer from
 | |
|     the horizontal centerline of the window.
 | |
| 
 | |
|     - Keypress 3: toggle the render window into and out of stereo
 | |
|     mode.  By default, red-blue stereo pairs are created. Some systems
 | |
|     support Crystal Eyes LCD stereo glasses; you have to invoke
 | |
|     SetStereoTypeToCrystalEyes() on the rendering window.  Note: to
 | |
|     use stereo you also need to pass a stereo=1 keyword argument to
 | |
|     the constructor.
 | |
| 
 | |
|     - Keypress e: exit the application.
 | |
| 
 | |
|     - Keypress f: fly to the picked point
 | |
| 
 | |
|     - Keypress p: perform a pick operation. The render window interactor
 | |
|     has an internal instance of vtkCellPicker that it uses to pick. 
 | |
| 
 | |
|     - Keypress r: reset the camera view along the current view
 | |
|     direction. Centers the actors and moves the camera so that all actors
 | |
|     are visible.
 | |
| 
 | |
|     - Keypress s: modify the representation of all actors so that they
 | |
|     are surfaces. 
 | |
| 
 | |
|     - Keypress u: invoke the user-defined function. Typically, this
 | |
|     keypress will bring up an interactor that you can type commands in.
 | |
| 
 | |
|     - Keypress w: modify the representation of all actors so that they
 | |
|     are wireframe.
 | |
|     """
 | |
|     
 | |
|     def __init__(self, parent=None, name=None, *args, **kw):
 | |
|         # the current button
 | |
|         self._ActiveButton = 0
 | |
| 
 | |
|         # private attributes
 | |
|         self.__oldFocus = None
 | |
|         self.__saveX = 0
 | |
|         self.__saveY = 0
 | |
|         self.__saveState = 0
 | |
|         self.__connected = 0  # is QT->VTK connection done?
 | |
| 
 | |
|         # do special handling of some keywords:
 | |
|         # stereo, rw
 | |
|         
 | |
|         stereo = 0
 | |
|         
 | |
|         if kw.has_key('stereo'):
 | |
|             if kw['stereo']:
 | |
|                 stereo = 1
 | |
|             del kw['stereo']
 | |
| 
 | |
|         rw = None
 | |
| 
 | |
|         if kw.has_key('rw'):
 | |
|             rw = kw['rw']
 | |
|             del kw['rw']
 | |
| 
 | |
|         # create qt-level widget
 | |
|         # You cannot pass kw anymore, you'll a TypeError: keyword arguments are not supported
 | |
|         # http://goldenspud.com/webrog/archives/2004/07/20/pyqt-platform-inconsistencies/
 | |
|         apply(qt.QWidget.__init__, (self,parent,name) + args)
 | |
| 
 | |
|         if rw: # user-supplied render window
 | |
|             self._RenderWindow = rw
 | |
|         else:
 | |
|             self._RenderWindow = vtk.vtkRenderWindow()
 | |
| 
 | |
|         if stereo: # stereo mode
 | |
|             self._RenderWindow.StereoCapableWindowOn()
 | |
|             self._RenderWindow.SetStereoTypeToCrystalEyes()
 | |
| 
 | |
|         self._Iren = vtk.vtkGenericRenderWindowInteractor()
 | |
|         self._Iren.SetRenderWindow(self._RenderWindow)
 | |
| 
 | |
|         # do all the necessary qt setup
 | |
|         self.setBackgroundMode(2) # NoBackground
 | |
|         self.setMouseTracking(1) # get all mouse events
 | |
|         self.setFocusPolicy(2) # ClickFocus
 | |
|         if parent == None:
 | |
|             self.show()
 | |
|         
 | |
|         self._Timer = qt.QTimer(self, 'timer handler')
 | |
|         self.connect(self._Timer, qt.SIGNAL('timeout()'),
 | |
|                      self.TimerEvent)
 | |
| 
 | |
|         self._Iren.AddObserver('CreateTimerEvent', self.CreateTimer)
 | |
|         self._Iren.AddObserver('DestroyTimerEvent', self.DestroyTimer)
 | |
|         
 | |
|     def __getattr__(self, attr):
 | |
|         """Makes the object behave like a
 | |
|         vtkGenericRenderWindowInteractor"""
 | |
|         if attr == '__vtk__':
 | |
|             return lambda t=self._Iren: t
 | |
|         elif hasattr(self._Iren, attr):
 | |
|             return getattr(self._Iren, attr)
 | |
|         elif hasattr(qt.QWidget, attr):
 | |
|             return getattr(self.sipThis, attr)
 | |
|         else:
 | |
|             raise AttributeError, self.__class__.__name__ + \
 | |
|                   " has no attribute named " + attr
 | |
| 
 | |
|     def CreateTimer(self, obj, evt):
 | |
|         self._Timer.start(10)
 | |
| 
 | |
|     def DestroyTimer(self, obj, evt):
 | |
|         self._Timer.stop()
 | |
|         return 1
 | |
| 
 | |
|     def TimerEvent(self):
 | |
|         self._Iren.TimerEvent()
 | |
| 
 | |
|     def polish(self):
 | |
|         """Final initialization just before the widget is displayed."""
 | |
|         size = self.size()
 | |
|         self._Iren.SetSize(size.width(), size.height())
 | |
|         self._RenderWindow.SetWindowInfo(str(int(self.winId())))
 | |
|         self._Iren.ConfigureEvent()
 | |
|         self.__connected = 1
 | |
|         
 | |
|     def show(self):
 | |
|         qt.QWidget.show(self)
 | |
|         self.update() # needed for initial contents display on Win32
 | |
| 
 | |
|     def paintEvent(self,ev):
 | |
|         if self.__connected:
 | |
|             self.Render()
 | |
| 
 | |
|     def resizeEvent(self,ev):
 | |
|         size = self.size()
 | |
|         self._Iren.SetSize(size.width(), size.height())
 | |
|         self._Iren.ConfigureEvent()
 | |
|         self.update()
 | |
| 
 | |
|     def _GetCtrlShift(self, ev):
 | |
|         ctrl, shift = 0, 0
 | |
|         if hasattr(ev, 'state'):
 | |
|             if (ev.state() & 8):
 | |
|                 shift = 1
 | |
|             if (ev.state() & 16):
 | |
|                 ctrl = 1
 | |
|         elif self.__saveState:
 | |
|             if (self.__saveState & 8):
 | |
|                 shift = 1
 | |
|             if (self.__saveState & 16):
 | |
|                 ctrl = 1            
 | |
|         return ctrl, shift
 | |
| 
 | |
|     def enterEvent(self,ev):
 | |
|         if not self.hasFocus():
 | |
|             self.__oldFocus = self.focusWidget()
 | |
|             self.setFocus()
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY,
 | |
|                                             ctrl, shift, chr(0), 0, None)
 | |
|         self._Iren.EnterEvent()
 | |
| 
 | |
|     def leaveEvent(self,ev):
 | |
|         if (self.__saveState & 0x7) == 0 and self.__oldFocus:
 | |
|             self.__oldFocus.setFocus()
 | |
|             self.__oldFocus = None
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY,
 | |
|                                             ctrl, shift, chr(0), 0, None)
 | |
|         self._Iren.LeaveEvent()
 | |
| 
 | |
|     def mousePressEvent(self,ev):
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         repeat = 0
 | |
|         if ev.type() == qt.QEvent.MouseButtonDblClick:
 | |
|           repeat = 1
 | |
|         self._Iren.SetEventInformationFlipY(ev.x(), ev.y(),
 | |
|                                             ctrl, shift, chr(0), repeat, None)
 | |
| 
 | |
|         self._ActiveButton = 0
 | |
|         if ev.button() == 1:
 | |
|             self._Iren.LeftButtonPressEvent()
 | |
|             self._ActiveButton = 'Left'
 | |
|         elif ev.button() == 2:
 | |
|             self._Iren.RightButtonPressEvent()
 | |
|             self._ActiveButton = 'Right'
 | |
|         elif ev.button() == 4:
 | |
|             self._Iren.MiddleButtonPressEvent()
 | |
|             self._ActiveButton = 'Middle'
 | |
| 
 | |
|     def mouseReleaseEvent(self,ev):
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         self._Iren.SetEventInformationFlipY(ev.x(), ev.y(),
 | |
|                                             ctrl, shift, chr(0), 0, None)
 | |
|         
 | |
|         if self._ActiveButton == 'Right':
 | |
|             self._Iren.RightButtonReleaseEvent()
 | |
|         elif self._ActiveButton == 'Left':
 | |
|             self._Iren.LeftButtonReleaseEvent()
 | |
|         elif self._ActiveButton == 'Middle':
 | |
|             self._Iren.MiddleButtonReleaseEvent()
 | |
| 
 | |
|     def mouseMoveEvent(self,ev):
 | |
|         self.__saveState = ev.state()
 | |
|         self.__saveX = ev.x()
 | |
|         self.__saveY = ev.y()
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         self._Iren.SetEventInformationFlipY(ev.x(), ev.y(),
 | |
|                                             ctrl, shift, chr(0), 0, None)
 | |
|         self._Iren.MouseMoveEvent()
 | |
| 
 | |
|     def keyPressEvent(self,ev):
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         key = chr(0)
 | |
|         if ev.key() < 256:
 | |
|             key = str(ev.text())
 | |
| 
 | |
|         self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY,
 | |
|                                             ctrl, shift, key, 0, None)
 | |
|         self._Iren.KeyPressEvent()
 | |
|         self._Iren.CharEvent()
 | |
|         
 | |
|     def keyReleaseEvent(self,ev):
 | |
|         ctrl, shift = self._GetCtrlShift(ev)
 | |
|         key = chr(0)
 | |
|         if ev.key() < 256:
 | |
|             key = chr(ev.key())
 | |
| 
 | |
|         self._Iren.SetEventInformationFlipY(self.__saveX, self.__saveY,
 | |
|                                             ctrl, shift, key, 0, None)
 | |
|         self._Iren.KeyReleaseEvent()
 | |
| 
 | |
|     def GetRenderWindow(self):
 | |
|         return self._RenderWindow
 | |
| 
 | |
|     def Render(self):
 | |
|         self._RenderWindow.Render()
 | |
| 
 | |
| 
 | |
| #-----------------------------------------------------------------------  
 | |
| def QVTKRenderWidgetConeExample():    
 | |
|     """A simple example that uses the QVTKRenderWindowInteractor
 | |
|     class.  """
 | |
|     
 | |
|     # every QT app needs an app
 | |
|     app = qt.QApplication(['QVTKRenderWindowInteractor'])
 | |
| 
 | |
|     # create the widget
 | |
|     widget = QVTKRenderWindowInteractor()
 | |
|     widget.Initialize()
 | |
|     widget.Start()
 | |
|     # if you dont want the 'q' key to exit comment this.
 | |
|     widget.AddObserver("ExitEvent", lambda o, e, a=app: a.quit())
 | |
| 
 | |
|     ren = vtk.vtkRenderer()
 | |
|     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)
 | |
| 
 | |
|     # show the widget
 | |
|     widget.show()
 | |
|     # close the application when window is closed
 | |
|     app.setMainWidget(widget)
 | |
|     # start event processing
 | |
|     app.exec_loop()
 | |
|     
 | |
| if __name__ == "__main__":
 | |
|     QVTKRenderWidgetConeExample()
 | |
| 
 | |
| 
 |