[vtkusers] Pls help! tk gui window disappears when i start the vtkRenderWindowInteractor

john jss at mensa.org.au
Sun Mar 12 21:59:06 EDT 2017


Hi good peoples,

I'm wondering if someone can help me with an issue I'm seeing after
updating an old vtk/tcl script to work with new VTK.

The updates i made were things like changing the image pipeline
filters to use SetInputConnection, instead of the deprecated old
SetInput, and other minor updates.

Basically, after the updates, the script works fine except that if when
I add command to start the vtkRenderWindowInteractor, the little TK gui
I've built does not appear.

If i leave out the command to start the vtkRenderWindowInteractor
(iren Start), then my tk gui appears, and I can use it to update some
parameters of the renderer, and the the gui has a Render button
which calls renWin Render to update the render window, and that's all
working fine. But in this state, the render window cannot be interacted
with. I can't zoom or rotate the view :-(

Back when I had this working on VTK 4 or 5, I'm sure I had the TK gui
up, and working, while at the same time being able to interact with the
rendered window.

I've tried with VTK 6.3 and 7.1, and behaviour is the same.

I am basically a beginner with TCL/TK & VTK, so I've tried various
things but had no success. I'm sure I must be just missing something
relatively simple.

I'd be happy with any solution that lets me use my tk gui, and the
rendered window, even if only one window is active at a time, eg, I
tried to get the "u" UserEvent of the vtkRenderWindowInteractor mapped
so it would bring up the tk gui, but i couldn't get that to work.
With most of the hacks i tried, the "u" button did nothing, and when i
did get it to do something, all it did was bring up some blank windows
called vtkInteract, which didn't seem to respond to anything i did with
it.

If i could get a key mapped which would pause the
vtkRenderWindowInteractor and bring up my tk gui so i could make
adjustments in the gui, then click a button to re-activate the
vtkRenderWindowInteractor, that would be fine.

If anyone can have a quick look at my script below, and tell me how to
get my TK gui working whilst also being able to have interaction on the
vtkRenderWindowInteractor working, that'd be awsm.

Many thanks,
John



#!/bin/sh
# pse3d.tcl v1.2 2003-03-04, updated 2017-03-13
# Author: me
# usage > psed3d.tcl [data_path] data_filename
#
# TCL script to view a power spectrum estimate in 3D, using VTK (the Visualisation Toolkit) and data-files 
# generated by my psef (power spectrum estimate and filter) program.
#
# If your TCLLIBPATH or LD_LIBRARY_PATH are not set correctly for VTK, you may need to use the vtk executable 
# to ensure that wish can find the VTK packages and shared libraries.
# usage for bad VTK setup > vtk pse3D.tcl [data_path] data_filename
#
# "u" displays the vtk interactor command dialog.
# the next line restarts using wish \
exec wish "$0" "$@"

package require vtk
package require vtkinteraction
if { [catch {set VTK_DATA $env(VTK_DATA)}] != 0} { set VTK_DATA "/usr/local/bin/jss/.vsa/pses/" }
puts ""; puts "Starting up."

set colour_scale 1000
set colour_scale_max 100000
set colour_scale_max_resolution 10000
set colour_scale_max_max 1000000
set colour_scale_resolution 10
set colour_scale_resolution_max 1000
set decimation 0.8
set decimation_resolution 0.01
set xAxisLabel "Frequency (Hz)"
set yAxisLabel "Amplitude (dB)"
set zAxisLabel "Time (%)"

###############################
puts "Getting datafile parameters:"
vtkPolyDataReader reader
if $argc==1 { set datafile $argv };
#if $argc==1 { set datafile $VTK_DATA/$argv };
if $argc==2 { 
    set VTK_DATA [lindex $argv 0];  set datafilename [lindex $argv 1] ; 
    set datafile $VTK_DATA/$datafilename ; puts "datafilename=<$datafilename>" 
};
puts "  VTK_DATA=<$VTK_DATA>"
puts "  datafile=<$datafile>"
reader SetFileName "$datafile";

reader OpenVTKFile
reader ReadHeader
set HeaderString [reader GetHeader]
puts "  HeaderString=<$HeaderString>"
reader CloseVTKFile

#remap = to _  and - to _ giving Floor=-100 => Floor__100 ... so wordend works
set HeaderString [string map {= _ - _} $HeaderString]
#get "Floor__XXX "
set DBindex [string first "Floor" $HeaderString]
set DBindex_end [string wordend $HeaderString $DBindex]
set DBstring [string range $HeaderString $DBindex $DBindex_end]
#trim trailing space
set DBstring [string trimright $DBstring]
#get index of last (2nd) _
set DBindex [string last "_" $DBstring]
set DBindex_end [string wordend $DBstring $DBindex]
set DBstring [string range $DBstring $DBindex $DBindex_end]
#convert _ to - 
set Floor [string map {_ -} $DBstring]
#set Floor [string trimleft $DBstring _]
puts "  Floor = $Floor dB"

###############################
vtkRenderer ren1
    ren1 BackingStoreOn

vtkRenderWindow renWin
    renWin AddRenderer ren1

vtkRenderWindowInteractor iren
    iren SetRenderWindow renWin

puts "RenderWindow, Renderer and Interactor created."
    
###############################
puts "Building the image pipeline:"

vtkTriangleFilter cutTriangles
cutTriangles SetInputConnection [reader GetOutputPort]

vtkDecimatePro deci
    deci SetInputConnection [cutTriangles GetOutputPort]
    deci SetTargetReduction $decimation
    deci BoundaryVertexDeletionOff
    deci PreserveTopologyOn
    #these options are for vtkDecimate not vtkDecimatePro
    #deci PreserveEdgesOn
    #set decimationInitialError [deci GetInitialError]
    #puts "decimationInitialError=<$decimationInitialError>"
    #deci SetInitialError blah
    #deci SetErrorIncrement blah

#may not need geometry filter
vtkGeometryFilter geometry
    geometry SetInputConnection [deci GetOutputPort]

#Create a vtkPolyDataNormals filter to calculate the normals of the data set.
vtkPolyDataNormals normals
    normals SetInputConnection [geometry GetOutputPort]

vtkPolyDataMapper map
    map SetInputConnection [geometry GetOutputPort]

#map ScalarVisibilityOn
map ImmediateModeRenderingOff
map SetScalarRange 0 $colour_scale

vtkActor surfaceActor
surfaceActor SetMapper map
[surfaceActor GetProperty] SetDiffuseColor 1.0000 0.3882 0.2784
[surfaceActor GetProperty] SetSpecularColor 1 1 1
[surfaceActor GetProperty] SetSpecular .4
[surfaceActor GetProperty] SetSpecularPower 50
puts "Image pipeline built."

#create HeadLight and add to renderer
vtkLight hlight
hlight SetLightTypeToHeadlight
hlight SetIntensity 1.0
ren1 AddLight hlight

vtkLight keyLight
keyLight SetLightTypeToSceneLight
keyLight SetPosition 0.5 1.0 1.0
keyLight SetIntensity 1.0
keyLight SetColor 1 1 0.9
ren1 AddLight keyLight

vtkLight rightLight
rightLight SetLightTypeToSceneLight
rightLight SetPosition 1.0 1.0 0.5
rightLight SetIntensity 0.5
rightLight SetColor 1 1 0.9
ren1 AddLight rightLight
puts "HeadLight and SceneLights added to renderer."

#Add the actors to the renderer, set the background and size
iren LightFollowCameraOff
ren1 AddActor surfaceActor
ren1 SetBackground 0 0 0
renWin SetSize 800 800
renWin SetWindowName "VorpalLab - 3D Power Spectrum Estimate"
puts "Actors added to renderer, background and size set."

#[ren1 GetActiveCamera] SetFocalPoint 0 0 0    ### 0 0 0 is the default
#[ren1 GetActiveCamera] SetPosition 0 0 -1
[ren1 GetActiveCamera] Azimuth 20
[ren1 GetActiveCamera] SetViewUp 0 1 0
[ren1 GetActiveCamera] Elevation 20
#[ren1 GetActiveCamera] Dolly 1.0
ren1 ResetCamera
ren1 ResetCameraClippingRange
set cam1 [ren1 GetActiveCamera]
$cam1 Zoom 1.4
puts "Camera positioned and zoomed."

puts "Setting up axes:"
#we want to reverse the labelling of the z axis tho
#vtkAxisActor2D zaxis

#vtkDouble xmin xmax ymin ymax zmin zmax;
#vtkFloatArray ranges;
vtkDoubleArray ranges;
   ranges SetNumberOfValues 6

#Create a vtkCubeAxesActor2D.  Use the outer edges of the bounding box to
#draw the axes.  Add the actor to the renderer.
vtkCubeAxesActor2D axes
    axes SetInputConnection [normals GetOutputPort]
    axes SetCamera [ren1 GetActiveCamera]
    set ranges [axes GetRanges]
    axes SetNumberOfLabels 2
    axes SetRanges 0 20050 $Floor 0 100 0
    axes UseRangesOn
    #[axes GetZAxisActor2D] AdjustLabelsOn
    axes SetLabelFormat "%6.6g"
    axes SetFlyModeToOuterEdges
    axes SetFontFactor 0.8
    axes SetXLabel $xAxisLabel
    axes SetYLabel $yAxisLabel
    axes SetZLabel $zAxisLabel
    [axes GetProperty] SetColor 1 1 1

    ren1 AddViewProp axes

puts "About to start rendering."
renWin Render
##renWin SetFileName pse.ppm
##renWin SaveImageAsPPM

puts "Three-D PSE up and running."
puts "Press \"q\" in the PSE window to quit. Use the mouse to rotate and zoom."

#prevent the tk window from showing up then start the event loop
#wm withdraw .

###############################
puts "" ; puts "Building the TK controls GUI:"

wm title . "3D PSE Controls"

#We first create a Tk frame into which we will pack all sliders.
frame .sliders

#Next we create a scale slider:
set scolourscale [scale .sliders.scolourscale \
	-from 1 -to $colour_scale_max \
	-res $colour_scale_resolution \
        -orient horizontal \
        -label "Colour Gradient:" \
        -command setColourScale]
#Slider widget is initialized using the value obtained from corresponding VTK object
$scolourscale set $colour_scale
#button callback:
proc setColourScale {colour_scale} {
    map SetScalarRange 0 $colour_scale
    #Use a separate button to render the scene in order to improve the responsiveness of
    #the slider, which is too slow if e ender here while slider is being moved
    #renWin Render
}

#Decimation slider:
set sdecimation [scale .sliders.sdecimation \
        -from 0 -to 1 -res $decimation_resolution  \
        -orient horizontal \
        -label "Decimation:" \
        -command setDecimation]
$sdecimation set $decimation
proc setDecimation {decimation} {
    deci SetTargetReduction $decimation
}

#Slider to limit maximum of colourscale parameter:
set scolourscalemax [scale .sliders.scolourscalemax \
        -from 10000 -to $colour_scale_max_max -res $colour_scale_max_resolution  \
        -orient horizontal \
        -label "Colour Gradient Maximum:" \
        -command setColourscalemax]
$scolourscalemax set $colour_scale_max
proc setColourscalemax {colourscalemax} {
    .sliders.scolourscale configure -to $colourscalemax
}

#Slider to set the resolution (smallest increment) of the colour scale:
set scolourscaleres [scale .sliders.scolourscaleres \
        -from 10 -to $colour_scale_resolution_max -res 10  \
        -orient horizontal \
        -label "Colour Gradient Resolution:" \
        -command setColourscaleres]
$scolourscaleres set $colour_scale_resolution
proc setColourscaleres {colourscaleres} {
    .sliders.scolourscale configure -res $colourscaleres
}

#Create frame for buttons:
frame .buttons1

#Quit button to trigger the builtin exit callback
button .buttons1.quit -text "Quit" -command ::vtk::cb_exit

#Render button to update rendering:
button .buttons1.render -text "Render" -command TkRender
proc TkRender {} {
    renWin Render
}

#pack the buttons into the current frame:
pack .buttons1.render .buttons1.quit -side left -anchor nw -fill both -expand yes

frame .buttons2
#Button for Immediate mode rendering - ON
button .buttons2.immediateOn -text "IMR On" -command ImOn
proc ImOn {} {
    map ImmediateModeRenderingOn 
}
#Button for Immediate mode rendering - OFF
button .buttons2.immediateOff -text "IMR Off" -command ImOff
proc ImOff {} {
    map ImmediateModeRenderingOff
}
pack .buttons2.immediateOn .buttons2.immediateOff -side left -anchor nw -fill both -expand yes

# Finally we pack all sliders on top of each other (-side top)
pack $scolourscale $scolourscaleres $scolourscalemax $sdecimation -side top -anchor nw -fill both
pack .sliders .buttons2 .buttons1 -side top -fill both -expand yes

# Set up a check for aborting rendering. This doesnt seem to work
#proc TkCheckAbort {} {
#  set foo [renWin GetEventPending]
#  if {$foo != 0} {renWin SetAbortRender 1}
#}
#renWin AddObserver AbortCheckEvent {TkCheckAbort}
puts "TK GUI is built"
###############################

# We set the window manager (wm command) so that it registers a
# command to handle the WM_DELETE_WINDOW protocal request. This
# request is triggered when the widget is closed using the standard
# window manager icons or buttons. In this case the exit callback
# will be called and it will free up any objects we created then exit
# the application.
wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit

# Set the user method (bound to key 'u')
iren AddObserver UserEvent {wm deiconify .vtkInteract}
#iren AddObserver UserEvent {wm deiconify .}
#iren AddObserver UserEvent {TkCheckAbort}
#iren AddObserver UserEvent {iren Disable}

#wm deiconify .
#wm withdraw .

#Only needed if this script is run from Tcl shell (tclsh) instead of a Tk shell (wish):
#tkwait window .

#iren Initialize

#if i start the vtkRenderWindowInteractor here, then my tk gui does not appear :-(
#iren Start



More information about the vtkusers mailing list