vtk用户指南 第十八章 与窗口系统集成

        在使用VTK的某些时候,您可能想要修改默认的交互行为(在vtkRenderWindowInteractor中)或为基于VTK的应用程序添加图形用户界面(GUI)。本节将解释如何为许多常见的用户界面工具包执行此操作。最新的和新的例子将在VTK/ examples /GUI源目录中找到。为了有效地使用这一章,我们建议您从阅读下一节管理交互样式开始。然后(将VTK嵌入到GUI中)查看第423页的“GUI交互的一般指南”,然后只有适合您的用户界面的小节。如果您使用的不是这里介绍的GUI,请阅读与您的GUI类似的子节。

18.1 vtkRenderWindow交互样式

        类vtkRenderWindowInteractor捕获渲染窗口中的鼠标和键盘事件,将窗口系统特定事件转换为VTK事件(这些在Common/ vtkCommand.h中定义),然后将翻译的VTK事件分派给另一个类-交互器样式。因此,要向VTK添加一种新的交互样式,您需要从vtkInteractorStyle派生一个新类。例如,类vtkInteractorStyleTrackball实现了在第45页的“vtkRenderWindowInteractor”中描述的trackball样式的交互。vtkInteractorStyleJoystickActor或vtkInteractorStyleJoystickCamera实现同一节中描述的操纵杆交互样式。另一个选择是使用类vtkInteractorStyleUser。这个类允许用户定义一个新的交互器样式,而不需要子类化。

        基本上,其工作方式如下。vtkrenderwindowwinteractor拦截与之关联的vtkRenderWindow中发生的事件。回想一下,在实例化时,vtkRenderWindowInteractor实际上实例化了一个特定于设备/窗口的实现——vtkXRenderWindowInteractor (Unix)或vtkWin32RenderWindowInteractor (Windows)。当调用vtkRenderWindowInteractor::Start()方法时,事件拦截被启用。这些事件依次转发到vtkRenderWindowInteractor::InteractorStyle实例。交互器样式会适当地处理事件。

这里列出了可用的交互器样式,并简要介绍了每种样式的功能。

•vtkInteractorStyleJoystickActor -实现操纵杆风格的演员操作。

•vtkInteractorStyleJoystickCamera -实现操纵杆风格的相机操作。

•vtkInteractorStyleTrackballActor -实现轨迹球风格的演员操作。

•vtkInteractorStyleTrackballCamera -实现轨迹球风格的相机操作。

•vtkInteractorStyleSwitch -管理轨迹球和操纵杆模式之间的切换,以及相机和对象(演员)模式。它通过拦截击键并在内部切换到上面列出的一种模式来实现这一点。(回想一下45页的“vtkRenderWindowInteractor”,Keypress j / Keypress t在轨迹球和操纵杆模式之间切换,Keypress c / Keypress a在相机和演员模式之间切换)

•vtkInteractorStyleFlight -一个特殊的类,允许用户“飞越”复杂的场景。

•vtkInteractorStyleImage -一个专门为2D图像设计的交互器样式。这个类通过鼠标运动执行窗口和水平调整,以及平移和小车约束到x-y平面。

•vtkInteractorStyleUnicam -单按钮相机操作。旋转、缩放和平移都可以用一个鼠标按钮执行。

•vtkInteractorStyleTerrain -以恒定的视向上矢量(在z方向)围绕物体移动相机。相机的移动结合了仰角,方位角和变焦。

•vtkInteractorStyleRubberBandZoom -支持通过在渲染窗口中绘制矩形来放大对象。

如果其中一种交互器样式不适合您的需要,您可以创建自己的交互器样式。有两种方法可以创建您自己的。首先,您可以从vtkInteractorStyle继承子类并覆盖适当的虚拟方法。其次,你可以创建观察者直接观察vtkRenderWindowInteractor(见“添加vtkRenderWindowInteractor观察者”在第47页),并采取适当的行动,注册的事件被观察。从vtkInteractorStyle子类化需要重写以下方法(如VTK/Rendering/vtkInteractorStyle.h中所述):

// Description:
 // Generic event bindings must be overridden in subclasses.
 virtual void OnMouseMove() {}
 virtual void OnLeftButtonDown() {}
 virtual void OnLeftButtonUp() {}
 virtual void OnMiddleButtonDown() {}
 virtual void OnMiddleButtonUp() {}
 virtual void OnRightButtonDown() {}
 virtual void OnRightButtonUp() {}
virtual void OnMouseWheelForward() {}
virtual void OnMouseWheelBackward() {}
 // Description:
 // OnChar implements keyboard functions, but subclasses can override
// this behavior.
 virtual void OnChar()
 virtual void OnKeyDown() {}
 virtual void OnKeyUp() {}
 virtual void OnKeyPress() {}
 virtual void OnKeyRelease() {}
 // Description:
 // These are more esoteric events, but are useful in some cases.
virtual void OnExpose() {}
virtual void OnConfigure() {}
 virtual void OnEnter() {}
 virtual void OnLeave() {}

然后使用交互器样式,将它与vtkRenderWindowInteractor关联
SetInteractorStyle()方法。
开发自己风格的第二种方法包括创建一组命令/观察者来实现所需的行为(参见第47页的“添加vtkRenderWindowInteractor观察者”示例)。这提供了更大的灵活性和将代码绑定在一起而不受对象继承约束的能力。

18.2 GUI交互的一般准则

在很大程度上,VTK被设计成将功能对象与用户界面隔离开来。这样做是为了可移植性和灵活性。但是你迟早需要创建一个用户界面,所以我们提供了一些钩子来帮助你完成这个过程。这些钩子被称为用户方法,它们将在第3章中讨论(参见第29页的“用户方法、观察者和命令”)。回想一下,VTK中用户方法的本质是任何类都可以调用事件。如果观察者注册到调用事件的类,则执行vtkCommand的实例,这是回调的实现。在开发用户界面时,不同的VTK类调用了各种各样的事件。下面提供了更有用的事件的部分列表。

子类的vtkInteractorStyle和vtk3DWidget(子类的vtkInteractorObserver)调用这些事件:

•StartInteractionEvent

•InteractionEvent

•EndInteractionEvent

一般来说,这些事件被调用时,你可能期望。按下鼠标按钮开始交互(StartInteractionEvent),移动鼠标需要交互响应(InteractionEvent),释放鼠标结束交互(EndInteractionEvent)。这些事件被设计为提供必要的控制来改变细节级别(参见第55页的“细节级别演员”)或以其他方式确保交互呈现性能。所有过滤器(vtkAlgorithm的子类)调用这些

事件

ProgressEvent

vtkRenderWindow调用这个事件(在渲染):

•AbortCheckEvent类(和子类)vtkActor, vtkVolume, vtkPropPicker, vtkPicker,和vtkWorldPointPicker调用这些事件,而采摘:

•PickEvent

•StartPickEvent(在采摘类中可用)

•EndPickEvent(在采摘类中可用)类vtkRenderWindowInteractor调用这些事件:

•StartPickEvent -当选择

•EndPickEvent -当选择

•UserEvent -响应“u”键在渲染窗口

•ExitEvent -响应“e”键在渲染窗口不要忘记,你可以定义自己的vtkInteractorStyle与它自己的一组特殊的回调。

        可以使用StartEvent、EndEvent和ProgressEvent调用向用户提供关于应用程序正在做什么以及需要多长时间的反馈。vtkDemandDrivenPipeline在所有过滤器上调用StartEvent和EndEvent。ProgressEvents由成像过滤器、一些阅读器和许多(但不是全部)可视化过滤器支持。AbortCheckEvent可以用来允许用户中断花费太长时间的渲染(需要使用vtkLODActors)。与虚拟方法相结合的选择事件可用于覆盖默认的VTK交互器行为,以便您可以创建自己的自定义交互样式。为了帮助您入门,请考虑以下两个合并了用户方法的示例。

        两者都是用Tcl编写的,但可以很容易地转换为其他语言。第一个定义了一个捕获ProgressEvent的过程,以显示vtkimagegaussianssmooth过滤器的进度。然后,它捕获EndEvent以更新显示以指示处理完成(图18-1)。代码基于VTK/Examples/GUI/Tcl/ progresseven . Tcl。

# Demonstrate filter ProgressEvent and GetProgress
package require vtk
# Image pipeline
vtkImageReader reader
reader SetDataByteOrderToLittleEndian
reader SetDataExtent 0 255 0 255 1 93
reader SetFilePrefix $env(VTK_DATA_ROOT)/Data/headsq/quarter
reader SetDataMask 0x7fff
vtkImageGaussianSmooth smooth
smooth SetInputConnection [reader GetOutputPort]
smooth AddObserver ProgressEvent {
.text configure -text \
Completed [expr [smooth GetProgress]*100.0] percent
update
}
smooth AddObserver EndEvent {
 .text configure -text Completed Processing
update
}
button .run -text Execute -command{
smooth Modified
smooth Update
}
label .text -text Waiting to Process
pack .run .text

        对于由多个过滤器组成的管道,每个过滤器都可以提供其进度的指示。您还可以创建通用的Tcl进程(而不是像这里这样内联地定义它们)并将它们分配给多个过滤器。

        第二个例子使用AbortCheckEvent来中断长渲染,如果鼠标事件处于挂起状态。(脚本基于VTK/Examples/Rendering/Tcl/AbortCheckEvent.tcl。)大部分代码是典型的VTK代码。关键的变化是必须使用vtkLODActor的实例;最好打开globalimmediatemoderrendering(),因为abort方法不能在显示列表处理过程中调用;最后,您必须添加几行代码来处理中止检查。在这个例子中,我们定义了一个名为TkCheckAbort的简单过程,它调用了vtkRenderWindow的GetEventPending()方法,然后在事件处于挂起状态时将AbortRender实例变量设置为1。mace模型的分辨率已经显著提高(图18-2(左)),所以你可以看到使用AbortRender逻辑的效果。请随意调整球体的分辨率以适应您的系统。如果一切正常,那么你应该能够快速旋转,然后缩放,而无需等待全分辨率球体在两个动作之间渲染(图18-2)。

package require vtk
package require vtkinteraction
# Create the RenderWindow, Renderer and both Actors
vtkRenderer ren1
vtkRenderWindow renWin
 renWin AddRenderer ren1
vtkRenderWindowInteractor iren
 iren SetRenderWindow renWin
# Create a sphere source and actor
vtkSphereSource sphere
sphere SetThetaResolution 40
sphere SetPhiResolution 40
vtkPolyDataMapper sphereMapper
 sphereMapper SetInputConnection [sphere GetOutputPort]
 sphereMapper GlobalImmediateModeRenderingOn
vtkLODActor sphereActor
 sphereActor SetMapper sphereMapper
# Create the spikes using a cone source and the sphere source
#
vtkConeSource cone
vtkGlyph3D glyph
 glyph SetInputConnection [sphere GetOutputPort]
 glyph SetSourceConnection [cone GetOutputPort]
 glyph SetVectorModeToUseNormal
 glyph SetScaleModeToScaleByVector
 glyph SetScaleFactor 0.25
vtkPolyDataMapper spikeMapper
 spikeMapper SetInput Connection [glyph GetOutput Port]
vtkLODActor spikeActor
 spikeActor SetMapper spikeMapper
# Add the actors to the renderer, set the background and size
ren1 AddActor sphereActor
ren1 AddActor spikeActor
ren1 SetBackground 0.1 0.2 0.4
renWin SetSize 300 300
iren AddObserver UserEvent {wm deiconify .vtkInteract}
set cam1 [ren1 GetActiveCamera]
$cam1 Zoom 1.4
iren Initialize
proc TkCheckAbort {} {
 if {[renWin GetEventPending] != 0} {renWin SetAbortRender 1}
}
renWin AddObserver AbortCheckMethod TkCheckAbort
# Prevent the tk window from appearing; start the event loop
wm withdraw .

18.3 X Windows, Xt和Motif

大多数传统的基于UNIX的应用程序使用Xt或Motif作为它们的小部件集。许多不直接使用Xt或Motif的人最终会在较低级别使用Xt。有两种常见的方法将VTK集成到基于Xt(或Motif)的应用程序中。这些例子可以在VTK/ examples /GUI/Motif源目录中找到。首先我们来看一个示例(Example1.cxx),其中VTK呈现窗口和应用程序UI位于不同的窗口(图18-3)。这有助于避免如果VTK和UI不使用相同的X视觉可能发生的一些问题。两个窗口将使用相同的X事件循环。考虑下面的示例应用程序。它绘制一个梅斯到一个VTK渲染窗口,然后创建一个Motif按钮和相关的回调在一个单独的窗口。

// Include OS specific include file to mix in X code
#include "vtkActor.h"
#include "vtkConeSource.h"
#include "vtkGlyph3D.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkXRenderWindowInteractor.h"
#include <Xm/PushB.h>
// void quit_cb(Widget,XtPointer,XtPointer);
// main (int argc, char *argv[])
{
 // X window stuff
 XtAppContext app;
 Widget toplevel, button;
 Display *display;
 // VTK stuff
 vtkRenderWindow *renWin;
 vtkRenderer *ren1;
 vtkActor *sphereActor1, *spikeActor1;
 vtkSphereSource *sphere;
 vtkConeSource *cone;
 vtkGlyph3D *glyph;
 vtkPolyDataMapper *sphereMapper, *spikeMapper;
 vtkXRenderWindowInteractor *iren;

代码的第一部分只包括所需的头文件和一个简单的回调原型,名为quit_cb。然后我们进入main函数并声明一些标准的X/Motif变量。然后像以前一样声明我们需要的VTK对象。这里唯一重要的变化是使用了vtkXRenderWindowInteractor子类而不是典型的vtkRenderWindowInteractor。这个子类允许我们访问一些特定于vtkXRenderWindowInteractor类的附加方法。

renWin = vtkRenderWindow::New();
 ren1 = vtkRenderer::New();
 renWin->AddRenderer(ren1);
 sphere = vtkSphereSource::New();
 sphereMapper = vtkPolyDataMapper::New();
 sphereMapper->SetInputConnection(sphere->GetOutputPort());
 sphereActor1 = vtkActor::New();
 sphereActor1->SetMapper(sphereMapper);
 cone = vtkConeSource::New();
 glyph = vtkGlyph3D::New();
 glyph->SetInputConnection(sphere->GetOutputPort());
 glyph->SetSourceConnection(cone->GetOutputPort());
 glyph->SetVectorModeToUseNormal();
 glyph->SetScaleModeToScaleByVector();
 glyph->SetScaleFactor(0.25);
 spikeMapper = vtkPolyDataMapper::New();
 spikeMapper->SetInputConnection(glyph->GetOutputPort());
 spikeActor1 = vtkActor::New();
 spikeActor1->SetMapper(spikeMapper);
 ren1->AddProp(sphereActor1);
 ren1->AddProp(spikeActor1);
 ren1->SetBackground(0.4,0.1,0.2);

以上代码是标准的VTK代码来创建狼牙棒。

// Do the xwindow ui stuff
 XtSetLanguageProc(NULL,NULL,NULL);
 toplevel = XtVaAppInitialize(&app,"Sample",NULL,0,
&argc,argv,NULL,NULL);
 // Get the display connection and give it to the renderer
 display = XtDisplay(toplevel);
 renWin->SetDisplayId(display);
 // We use an X specific interactor
 // since we have decided to make this an X program
 iren = vtkXRenderWindowInteractor::New();
 iren->SetRenderWindow(renWin);
 iren->Initialize(app);
 button = XtVaCreateManagedWidget("Exit",
xmPushButtonWidgetClass,
toplevel,XmNwidth, 50,
XmNheight, 50,NULL);
XtRealizeWidget(toplevel);
 XtAddCallback(button,XmNactivateCallback,quit_cb,NULL);
 XtAppMainLoop(app);
}
// Simple quit callback
void quit_cb(Widget w,XtPointer client_data,XtPointer call_data)
{
 exit(0);
}

最后,我们执行标准的Xt初始化并创建我们的顶层shell。接下来的几行非常重要。我们从顶层shell获得X显示id,并告诉呈现窗口使用相同的显示id。接下来,我们创建vtkXRenderWindowInteractor,设置它的渲染窗口,最后使用之前XtVaAppInitialize()调用的X应用程序上下文初始化它。然后使用标准的Xt/Motif调用来创建按钮,实现顶层shell,并为按钮分配回调函数。最后一步是启动XtAppMainLoop。quit_cb是一个简单的回调函数,它只是退出应用程序。在这种类型的方法中,在创建用户界面的其余部分之前初始化VTK渲染窗口交互器是至关重要的。否则一些事件可能无法正确处理。

现在我们将修改前面的示例,使呈现窗口成为用户界面的一部分(图18-4)。(修改后的源代码在VTK/Examples/GUI/Motif/Example2.cxx中。)这将需要我们创建一个顶层的外壳与可视的VTK可以用来渲染。幸运的是,vtkXOpenGLRenderWindow包含了一些方法来帮助你创建一个合适的顶层shell。以下示例中的大部分代码与前一个示例相同。我们将很快讨论这些差异。

// Include OS specific file to mix in X code
#include "vtkActor.h"
#include "vtkConeSource.h"
#include "vtkGlyph3D.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkSphereSource.h"
#include "vtkXOpenGLRenderWindow.h"
#include "vtkXRenderWindowInteractor.h"
#include <Xm/PushB.h>
#include <Xm/Form.h>
void quit_cb(Widget,XtPointer,XtPointer);
main (int argc, char *argv[])
{
 // X window stuff
 XtAppContext app;
 Widget toplevel, form, toplevel2, vtk;
 Widget button;
 int depth;
 Visual *vis;
 Display *display;
 Colormap col;
 // VTK stuff
 vtkXOpenGLRenderWindow *renWin;
 vtkRenderer *ren1;
 vtkActor *sphereActor1, *spikeActor1;
 vtkSphereSource *sphere;
 vtkConeSource *cone;
 vtkGlyph3D *glyph;
 vtkPolyDataMapper *sphereMapper, *spikeMapper;
 vtkXRenderWindowInteractor *iren;
 renWin = vtkXOpenGLRenderWindow::New();
 ren1 = vtkRenderer::New();
 renWin->AddRenderer(ren1);
 sphere = vtkSphereSource::New();
 sphereMapper = vtkPolyDataMapper::New();
 sphereMapper->SetInputConnection(sphere->GetOutputPort());
 sphereActor1 = vtkActor::New();
 sphereActor1->SetMapper(sphereMapper);
 cone = vtkConeSource::New();
 glyph = vtkGlyph3D::New();
 glyph->SetInputConnection(sphere->GetOutputPort());
 glyph->SetSourceConnection(cone->GetOutputPort());
 glyph->SetVectorModeToUseNormal();
 glyph->SetScaleModeToScaleByVector();
 glyph->SetScaleFactor(0.25);
 spikeMapper = vtkPolyDataMapper::New();
 spikeMapper->SetInputConnection(glyph->GetOutputPort());
 spikeActor1 = vtkActor::New();
 spikeActor1->SetMapper(spikeMapper);
 ren1->AddActor(sphereActor1);
 ren1->AddActor(spikeActor1);
 ren1->SetBackground(0.4,0.1,0.2);
// Do the xwindow ui stuff
 XtSetLanguageProc(NULL,NULL,NULL);
 toplevel = XtVaAppInitialize(&app,"Sample",NULL,0,
&argc,argv,NULL,NULL);

初始代码相对没有变化。在开始时,我们包含了一个额外的Motif头文件来支持Motif表单小部件。在main函数中,我们添加了一些额外的变量来存储一些额外的X属性。

// Get the display connection and give it to the renderer
 display = XtDisplay(toplevel);
 renWin->SetDisplayId(display);
 depth = renWin->GetDesiredDepth();
 vis = renWin->GetDesiredVisual();
 col = renWin->GetDesiredColormap();
 toplevel2 = XtVaCreateWidget("top2",
topLevelShellWidgetClass,toplevel,
 XmNdepth, depth,
 XmNvisual, vis,
 XmNcolormap, col,
 NULL);

这就是重大变化开始的地方。我们使用第一个顶层shell小部件来获得X显示连接。然后我们将渲染窗口设置为使用该显示连接,然后查询X深度,视觉和颜色映射最适合它使用。然后我们创建另一个顶层shell小部件,这次显式指定深度、颜色图和视觉效果。这样,第二个顶层外壳将适合VTK渲染。这个顶层外壳的所有子部件将具有与topplevel2相同的深度、颜色映射和视觉效果。

form = XtVaCreateWidget("form",xmFormWidgetClass, toplevel2, NULL);
 vtk = XtVaCreateManagedWidget("vtk",
xmPrimitiveWidgetClass, form,
 XmNwidth, 300, XmNheight, 300,
 XmNleftAttachment, XmATTACH_FORM,
 XmNrightAttachment, XmATTACH_FORM,
 XmNtopAttachment, XmATTACH_FORM,
 NULL);
 button = XtVaCreateManagedWidget("Exit",
xmPushButtonWidgetClass, form,
 XmNheight, 40,
 XmNbottomAttachment, XmATTACH_FORM,
 XmNtopAttachment, XmATTACH_WIDGET,
 XmNtopWidget, vtk,
 XmNleftAttachment, XmATTACH_FORM,
 XmNrightAttachment, XmATTACH_FORM,
 NULL);
 XtAddCallback(button,XmNactivateCallback,quit_cb,NULL);
 XtManageChild(form);
 XtRealizeWidget(toplevel2);
 XtMapWidget(toplevel2);
 // We use a X specific interactor
 // since we have decided to make this an X program
 iren = vtkXRenderWindowInteractor::New();
 iren->SetRenderWindow(renWin);
 iren->SetWidget(vtk);
 iren->Initialize(app);
 XtAppMainLoop(app);
}
/* quit when the Exit button is clicked*/
void quit_cb(Widget w,XtPointer client_data,XtPointer call_data)
{
 exit(0);
}

最后,我们创建了一些Motif小部件,包括一个xmPrimitiveWidgetClass,这是VTK将渲染成。添加表单小部件只是为了处理按钮和呈现窗口的布局。本例中使用SetWidget()调用来告诉交互器(以及呈现窗口)要使用哪个小部件进行呈现。

18.4 Microsoft Windows / Microsoft Foundation Classes (MFC)

在Windows环境中集成VTK的基础已经在前面展示过(参见第29页的“创建应用程序”)。您还可以开发基于mfc的应用程序,以两种不同的方式利用VTK。在基于MFC的应用程序中使用VTK的第一种方法是遵循VTK/Examples/GUI/Win32/SimpleCxx/Win32Cone.cxx的代码。在MFC应用程序中创建一个vtkRenderWindow,如果需要,可以使用基于MFC的窗口作为其父窗口。第二种方法是利用在Examples/GUI/Win32/SampleMFC子目录中提供的vtkMFCView, vtkMFCRenderView和vtkMFCDocument类。实际上,sample .exe应用程序是一个基于mfc的示例应用程序,它演示了这些类的用法。这个MDI应用程序(多文档界面)展示了如何打开几个VTK数据文件,并通过GUI与它们交互(图18-5)。您可以复制这些类,作为您自己的新MFC应用程序的起点。

18.5 Tcl / Tk

集成VTK与Tcl/Tk用户界面通常是一个相当容易的过程,感谢类,如vtkTkRenderWidget,和vtkTkImageViewerWidget。可以像使用任何其他Tk小部件一样使用这些类。最新资料及新例子可于VTK/
Examples/GUI/Tcl和VTK/ wrapped /Tcl源目录。考虑下面的例子取自VTK/Examples/GUI/Tcl/vtkTkRenderWidgetDemo.tcl。运行结果如图18-6所示。

package require vtk
package require vtkinteraction
# This script uses a vtkTkRenderWidget to
# create a Tk widget that is associated with
# a vtkRenderWindow.
# Create the GUI: a render widget and a quit
# button
wm withdraw .
toplevel .top
frame .top.f1
vtkTkRenderWidget .top.f1.r1 \
 -width 400 -height 400
button .top.btn -text Quit -command exit
pack .top.f1.r1 -side left -padx 3 -pady 3 -fill both \
-expand t
pack .top.f1 -fill both -expand t
pack .top.btn -fill x
# Get the render window associated with the widget.
set renWin [.top.f1.r1 GetRenderWindow]
vtkRenderer ren1
$renWin AddRenderer ren1
# Bind the mouse events
BindTkRenderWidget .top.f1.r1
# Create a Cone source and actor
vtkConeSource cone
vtkPolyDataMapper coneMapper
 coneMapper SetInputConnection [cone GetOutputPort]
 coneMapper GlobalImmediateModeRenderingOn
vtkLODActor coneActor
 coneActor SetMapper coneMapper
# Add the actors to the renderer, set the background
#
ren1 AddProp coneActor
ren1 SetBackground 0.1 0.2 0.4

第一行是标准的package require vtk命令,用于加载vtk Tcl包。vtkinteraction包包含用于处理渲染小部件的鼠标和键盘事件的默认绑定。具体来说,它定义了BindTkRenderWidget过程这些绑定用于特定的vtkTkRenderWidget。接下来,我们提取默认的顶层小部件,并创建一个名为.top的新部件。在某些系统上,您可能需要用下面的行来创建.top,而不是上面给出的行。

toplevel .top -visual best

接下来,我们以传统的Tk方式创建并打包框架、vtkTkRenderWidget和一个按钮。下一行查询它正在使用的底层呈现窗口的vtkTkRenderWidget。我们将其存储在一个名为renWin的变量中。然后我们创建一个渲染器,将其与渲染窗口关联,然后使用BindTkRenderWidget过程将鼠标事件绑定到vtkRenderWidget。最后我们以正常的方式创建锥体和演员。如果你愿意,渲染窗口可以作为创建vtkTkRenderWidget的参数提供,如下所示:

vtkRenderWindow renWin
vtkTkRenderWidget .top.f1.r1 \
-width 400 -height 400 -rw renWin

然后简单地使用renWin而不是$renWin,因为它现在是一个实例,而不是一个变量引用。

对于应用程序开发,您可能希望自定义事件处理。最好的方法是创建一个binding的副本。TCL和绑定。tcl位于VTK/ wrapped / tcl /vtkinteraction,然后编辑它以适应您的喜好。第一个文件的格式相当简单。它定义了将事件与特定Tcl过程关联起来的BindTkRenderWidget过程。另一个文件定义了这些过程。与vtkTkRenderWidget使用的相同技术可以与vtkTkImageViewerWidget一起用于图像处理。而不是有-rw选项和GetRenderWindow()方法,vtkTkImageViewerWidget支持-iv和GetImageViewer()。

当使用vtkTkWidget类时,你不应该使用像vtkRenderWindowInteractor这样的交互器类。通常,对于给定的窗口,您应该使用交互器或vtkTkWidget,但从不同时使用两者。

18.6 Java

可视化工具包包括一个专门设计的类,帮助您将VTK集成到基于Java的应用程序中。这是一个相当棘手的过程,因为Java没有提供任何支持本地代码集成的“公共”类。Java是一种多线程语言,而像X11R5这样的窗口系统不支持多线程用户界面,这使得这一工作变得更加困难。为了帮助克服这些困难,我们提供了一个名为vtkPanel的Java类。这个类与Java一起工作,使vtkRenderWindow看起来像一个普通的Java AWT画布。SimpleVTK.java示例位于VTK/ wrapped /Java子目录中。它使用了vtkPanel类。vtkPanel.java在VTK/ wrapped /Java/ VTK中。

18.7使用VTK与Qt

VTK现在包含许多类,可以很容易地将VTK功能集成到Qt应用程序中。与Qt相关的VTK源文件位于VTK/ guissupport /Qt目录下。Qt相关的VTK示例位于VTK/ examples /GUI/Qt目录下。的Qt支持VTK在默认情况下不启用,所以当你配置VTK,你必须打开Qt支持通过设置以下组CMake变量:•“

•VTK_USE_GUISUPPORT: BOOL =”VTK_USE_QT: BOOL =在

•“DESIRED_QT_VERSION: STRING = 4

•”QT_QMAKE_EXECUTABLE: FILEPATH = C: /全/道路/ / qmake

如果你打开BUILD_EXAMPLES除了设置所有必需的Qt变量,那么所有的例子在VTK /例子/ GUI / Qt目录也将构建VTK时建造的。或者您可以在构建VTK后单独构建它们。

如果您从头开始使用新的VTK构建树,请按照以下说明在cmake-gui或ccmake中交互式地进行这些设置:

•“配置vtk

•”打开VTK_USE_GUISUPPORT(高级)和VTK_USE_QT

•“配置vtk再次•”设置DESIRED_QT_VERSION(至4或3)

•“配置vtk再次

•”设置QT_QMAKE_EXECUTABLE

•“可选地打开BUILD_EXAMPLES

•”配置和生成

如果你想使用QVTKPluginWidget在Qt设计器应用程序,一定要建立一个配置匹配的设计器。默认情况下,在Visual Studio或Xcode构建中使用Release配置,或者在基于makefile的构建中设置CMAKE_BUILD_TYPE为“Release”。

构建完成后,复制文件QVTKWidgetPlugin.dll(或*. dll)。所以是*。(相当于Linux或Mac上的dylib)到Qt安装的“plugins/designer”文件夹。然后,当你打开设计器,你应该有“QVTKWidget”在Qt设计器的Widget框中可用,如下面的截图所示:

vtkEventQtSlotConnect类是一个适配器类,允许您将基于vtkObject的事件连接到基于QObject的插槽,这样当vtkObject事件被调用时,您的插槽被调用。该类的示例使用位于文件VTK/Examples/GUI/中的Form1::init方法中
Qt /事件/ GUI.ui.h。这个例子中的代码片段演示了将slot方法连接到基于vtkObject的事件是多么容易:

connections = vtkEventQtSlotConnect::New();
 // get right mouse pressed with high priority
 connections->Connect(qVTK1->GetRenderWindow()->GetInteractor(),
 vtkCommand::RightButtonPressEvent,
this,SLOT(popup( vtkObject*, unsigned long,
void*, void*, vtkCommand*)),
 popup1, 1.0);

本书为英文翻译而来,供学习vtk.js的人参考。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值