问题
I am attempting to write a program that displays and cycles through images of different file formats when the arrow keys are pressed. I have found that setting up my reader->mapper->actor pipeline and then starting my RenderWindowInteractor allows the actor to be rendered, but moving this code to a callback for the RenderWindowInteractor's KeyPressEvent does not allow the actor to be rendered. Are there additional steps required to set up a new actor once the event loop has started, or have I made some other mistake?
import vtk
#Create the renderer that will display our actors
ren = vtk.vtkRenderer()
actor = None
#Maps the data from the Nifti file 'filename' onto a vtkImageSlice actor
def LoadNifti():
# load head MRI in NIFTI format
reader = vtk.vtkNIFTIImageReader()
reader.SetFileName("head.nii")
reader.Update()
# Add an ImageSliceMapper, which maps data to an ImageSlice Actor
mapper = vtk.vtkImageSliceMapper()
#Set the slice position to the camera focal point
mapper.SliceAtFocalPointOn()
mapper.SetInputConnection(reader.GetOutputPort())
# Add an ImageSlice actor, which represents a slice as an image
global actor
actor = vtk.vtkImageSlice()
actor.SetMapper(mapper)
#Placeholder for when I have DICOM working
def ShowDICOM(filename):
pass
#Create a RenderWindow to display images from the Renderer
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
#Wrap the RenderWindow in a RenderWindowInteractor to catch key and mouse events
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
def foo():
LoadNifti()
ren.AddActor(actor)
##Extend the default functionality of the interactor and its style with custom listeners
def KeyPressEvent(obj, ev):
foo()
print("This verifies that the callback is triggered")
iren.AddObserver("KeyPressEvent", KeyPressEvent)
#Start the program
###########################################################################
# WHEN foo() IS PRESENT BELOW, THE ACTOR WILL RENDER IMMEDIATELY.
# WHEN foo() IS ABSENT BELOW, CALLING foo() BY TRIGGERING THE KeyPressEvent
# IS NOT SUFFICIENT TO HAVE THE ACTOR RENDER.
###########################################################################
foo()
#According to the docs, the Start method will initialize iren and render renWin automatically
iren.Start()
回答1:
Well, you definitely can add or remove actors inside a callback. To render the scene again immediately, simply call iren.Render()
.
When you start a renderer without any visible actors and without an explicitly defined camera, then ResetCamera
is typically required. Automatic ResetCamera
is only called once during the initialization, and this is the reason, why calling foo()
before iren.Start()
makes the object visible.
def foo():
LoadNifti()
ren.AddActor(actor)
ren.ResetCamera() # should that be necessary
iren.Render()
来源:https://stackoverflow.com/questions/54337397/rendering-an-actor-created-within-a-vtkcommand-callback