通过AddObserver添加LeftButtonPressEvent类型事件,不能响应。但改为InteractionEvent类型的就可以。我试了下,似乎vtkRenderWindowInteractor 会响应LeftButtonPressEvent类型事件。 于是为了能给物体添加点的拾取功能,先通过为 vtkRenderWindowInteractor * iren 添加消息响应类 class vtkLeftButtonPress : public vtkCommand { public: static vtkLeftButtonPress* New(){return new vtkLeftButtonPress;} void Delete(){delete this;}; void SetParameters(vtkRenderer* r){m_ren = r;} virtual void Execute(vtkObject * caller, unsigned long l, void *callData) { // if(!m_picker) return; vtkRenderWindowInteractor* iren = reinterpret_cast<vtkRenderWindowInteractor*>(caller); vtkAbstractPicker * picker = iren->GetPicker(); int *pickPos = iren->GetEventPosition(); picker->Pick((double)pickPos[0], (double)pickPos[1], 0.0, m_ren); } protected: vtkRenderer* m_ren; }; 然后 lbp->SetParameters(ren);把vtkRenderer传递进来,再添加事件处理 iren->AddObserver(vtkCommand::LeftButtonPressEvent, lbp); iren得到鼠标左击事件,并对vktPointPick进行PicK. 这样pointPicker就能收到EndPickEvent命令,并进行相应的处理, 我们为vtkPointPicker *pointPicker添加消息响应类 class vtkPrintPointID : public vtkCommand { public: static vtkPrintPointID* New(){return new vtkPrintPointID;} void Delete(){delete this;}; virtual void Execute(vtkObject *caller, unsigned long l, void *callData) { vtkPointPicker* ptPicker = reinterpret_cast<vtkPointPicker*>(caller); std::cout<<ptPicker->GetPointId()<<endl; } }; 最终就能显示点击顶点的索引号 主要源码: // Arrays.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: Arrays.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // This example demonstrate the use of VTK data arrays as attribute // data as well as field data. It creates geometry (vtkPolyData) as // well as attribute data explicitly. // first include the required header files for the vtk classes we are using #include "vtkActor.h" #include "vtkCellArray.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkIntArray.h" #include "vtkPointData.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkPointPicker.h" #include <iostream> #include "vtkCommand.h" class vtkLeftButtonPress : public vtkCommand { public: static vtkLeftButtonPress* New(){return new vtkLeftButtonPress;} void Delete(){delete this;}; void SetParameters(vtkRenderer* r){m_ren = r;} virtual void Execute(vtkObject * caller, unsigned long l, void *callData) { // if(!m_picker) return; vtkRenderWindowInteractor* iren = reinterpret_cast<vtkRenderWindowInteractor*>(caller); vtkAbstractPicker * picker = iren->GetPicker(); int *pickPos = iren->GetEventPosition(); picker->Pick((double)pickPos[0], (double)pickPos[1], 0.0, m_ren); } protected: vtkRenderer* m_ren; }; class vtkPrintPointID : public vtkCommand { public: static vtkPrintPointID* New(){return new vtkPrintPointID;} void Delete(){delete this;}; virtual void Execute(vtkObject *caller, unsigned long l, void *callData) { vtkPointPicker* ptPicker = reinterpret_cast<vtkPointPicker*>(caller); // ptPicker->Pick((double)pickPos[0], (double)pickPos[1], 0.0, g_ren1);//触发了EndPickEvent:在CHoleRepairDlg::OnLandmark()中的g_picker->AddObserver( vtkCommand::EndPickEvent, landmarkObserver ); std::cout<<ptPicker->GetPointId()<<endl; } }; int main() { int i; // Create a float array which represents the points. vtkFloatArray* pcoords = vtkFloatArray::New(); // Note that by default, an array has 1 component. // We have to change it to 3 for points pcoords->SetNumberOfComponents(3); // We ask pcoords to allocate room for at least 4 tuples // and set the number of tuples to 4. pcoords->SetNumberOfTuples(4); // Assign each tuple. There are 5 specialized versions of SetTuple: // SetTuple1 SetTuple2 SetTuple3 SetTuple4 SetTuple9 // These take 1, 2, 3, 4 and 9 components respectively. float pts[4][3] = { {0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0} }; for (i=0; i<4; i++) { pcoords->SetTuple(i, pts[i]); } // Create vtkPoints and assign pcoords as the internal data array. vtkPoints* points = vtkPoints::New(); points->SetData(pcoords); // Create the cells. In this case, a triangle strip with 2 triangles // (which can be represented by 4 points) vtkCellArray* strips = vtkCellArray::New(); strips->InsertNextCell(4); strips->InsertCellPoint(0); strips->InsertCellPoint(1); strips->InsertCellPoint(2); strips->InsertCellPoint(3); // Create an integer array with 4 tuples. Note that when using // InsertNextValue (or InsertNextTuple1 which is equivalent in // this situation), the array will expand automatically vtkIntArray* temperature = vtkIntArray::New(); temperature->SetName("Temperature"); temperature->InsertNextValue(10); temperature->InsertNextValue(200); temperature->InsertNextValue(10); temperature->InsertNextValue(10); // Create a double array. vtkDoubleArray * vorticity = vtkDoubleArray::New(); vorticity->SetName("Vorticity"); vorticity->InsertNextValue(2.7); vorticity->InsertNextValue(4.1); vorticity->InsertNextValue(5.3); vorticity->InsertNextValue(3.4); // Create the dataset. In this case, we create a vtkPolyData vtkPolyData* polydata = vtkPolyData::New(); // Assign points and cells polydata->SetPoints(points); polydata->SetStrips(strips); // Assign scalars polydata->GetPointData()->SetScalars(temperature); // Add the vorticity array. In this example, this field // is not used. polydata->GetPointData()->AddArray(vorticity); // Create the mapper and set the appropriate scalar range // (default is (0,1) vtkPolyDataMapper* mapper = vtkPolyDataMapper::New(); mapper->SetInput(polydata); mapper->SetScalarRange(0, 250); // Create an actor. vtkActor* actor = vtkActor::New(); actor->SetMapper(mapper); // Create the rendering objects. vtkRenderer* ren = vtkRenderer::New(); ren->AddActor(actor); vtkRenderWindow* renWin = vtkRenderWindow::New(); renWin->AddRenderer(ren); vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); vtkPointPicker * pointPicker = vtkPointPicker::New(); vtkLeftButtonPress * lbp = vtkLeftButtonPress::New(); lbp->SetParameters(ren); iren->AddObserver(vtkCommand::LeftButtonPressEvent, lbp); vtkPrintPointID *ppID = vtkPrintPointID::New(); pointPicker->AddObserver(vtkCommand::EndPickEvent, ppID); iren->SetPicker(pointPicker); //设置picker iren->Initialize(); iren->Start(); ppID->Delete(); pcoords->Delete(); points->Delete(); strips->Delete(); temperature->Delete(); vorticity->Delete(); polydata->Delete(); mapper->Delete(); actor->Delete(); ren->Delete(); renWin->Delete(); pointPicker->Delete(); iren->Delete(); return 0; }