How to get the key code in a vtk KeyPressEvent using python

Question:

I’m getting started with vtk (6) in python and have a problem handling KeyPressEvent. I want to subclass the vtkInteractorStyleTrackballCamera

if I use this pattern, my interactor style does not have getKeySym() and I can’t decode what key was pressed

    class KeyPressInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self,parent=None):
        self.AddObserver("MiddleButtonPressEvent",self.middleButtonPressEvent)
        self.AddObserver("MiddleButtonReleaseEvent",self.middleButtonReleaseEvent)
        self.AddObserver("KeyPressEvent",self.keyPress)

    def keyPress(self,obj,event):
        key = obj.GetKeySym() #Does not work
        print("key %s" % key)
        return

    def middleButtonPressEvent(self,obj,event):
        ...
        return

    def middleButtonReleaseEvent(self,obj,event):
        ...
        return

However if I use the factory vtkInteractorStyleTrackballCamera class and add observers with this pattern, the same keyPress() is able to access GetKeySym().

def KeyPress(obj,event):
    key = obj.GetKeySym() #works fine
    print("key %s" % key)

def MiddleButtonPressEvent(obj,event):
    ...
    return

def MiddleButtonReleaseEvent(obj,event):
    ...
    return
...
interactor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
    interactor.AddObserver("KeyPressEvent",KeyPress)
    interactor.AddObserver("MiddleButtonPressEvent",MiddleButtonPressEvent)
    interactor.AddObserver("MiddleButtonReleaseEvent",MiddleButtonReleaseEvent)

I’m a newbie, what should I do to get functionality in my class?

Asked By: M J Barrow

||

Answers:

Right I found a solution after checking the vtk doxygen for and seeing that vtkInteractorStyleTrackballCamera does not inherit from vtkRenderWindowInteractor which I had assumed in the example I was porting. I decided to pass my style class a parent so that it could access the RenderWindow GetKeySym(). It may not be the best solution, but here’s how as an FYI:

class KeyPressInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self,parent=None):
        self.parent = vtk.vtkRenderWindowInteractor()
        if(parent is not None):
            self.parent = parent

        self.AddObserver("KeyPressEvent",self.keyPress)

    def keyPress(self,obj,event):
        key = self.parent.GetKeySym()
...
    interactor = vtk.vtkRenderWindowInteractor()
    interactor.SetInteractorStyle(KeyPressInteractorStyle(parent = interactor))
Answered By: M J Barrow

If you are making an Interactor Style class I think it’s safe to assume it will be applied to an interactor as some point. I noticed in your solution you set the parent to be a vtk.vtkRenderWindowInteractor(). It would be better to set the parent to be the specific instance of vtkRenderWindowInteractor:

class MyInteractorStyle(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self,parent=None):
        self.parent = iren

        self.AddObserver("KeyPressEvent",self.keyPressEvent)

    def keyPressEvent(self,obj,event):
        key = self.parent.GetKeySym()
        if key == 'l':
            print(key)
        return

...

iren = vtk.vtkRenderWindowInteractor()

iren.SetInteractorStyle(MyInteractorStyle())

iren.SetRenderWindow(renWin)
renWin.Render()

iren.Initialize()
iren.Start()
Answered By: Thomas Butyn

I found this question by googling “vtk keypressevent python” and just wanted to share my solution as there is no need for subclassing vtkInteractorStyle:

def keypress_callback(obj, ev):
    key = obj.GetKeySym()
    print(key, 'was pressed')

render_interactor = vtk.vtkRenderWindowInteractor()
render_interactor.AddObserver('KeyPressEvent', keypress_callback, 1.0)
Answered By: max0r

This worked for me with vtk 9.2.0:

class KeyPressStyle(vtk.vtkInteractorStyleTrackballCamera):
    def __init__(self):
        super().__init__()
        self.AddObserver("KeyPressEvent", self.OnKeyPress)

    def OnKeyPress(self, obj, event):
        print(f"Key {obj.GetInteractor().GetKeySym()} pressed")

def main():
    ren1 = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren1)
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
   
    renWin.Render()
    iren.SetInteractorStyle(vtk.KeyPressStyle())
Answered By: Paul Weibert
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.