QT用vtk自带鼠标事件获取点坐标,鼠标事件回调函数未执行

目的

想通过鼠标左键实现点云旋转变换

遇到问题

操作点云时进不去vtk鼠标控件的回调函数

解决方式

无意间看到这位老哥的博文PCL1.12.1+VTK9.1+Qt5.14.2VS创建Qt项目在widget上显示点云,其中提到QOpenGLWidget界面实时刷新问题
即viewer调用回调函数后增加一行代码,实现界面的重新渲染

Viewer->getRenderWindow()->Render();

自己实现代码参考

QtWidgetsApplication_PCL.h

class QtWidgetsApplication_PCL : public QMainWindow 
{
    Q_OBJECT

public:
    QtWidgetsApplication_PCL(QWidget *parent = nullptr);
    ~QtWidgetsApplication_PCL();
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
    int flag , xb, yb;
    static void pp_callback(const pcl::visualization::MouseEvent& event, void* args);//回调函数设置成静态函数方便访问 类成员
private slots:
    void showCloud();
private:
    Ui::QtWidgetsApplication_PCLClass ui;
    pcl::visualization::PCLVisualizer::Ptr view;

};

对于回调函数放入类中的实现方式参考这篇博客其中将回调函数第二个参数从以前的结构体换成类对象感觉受益匪浅。

QtWidgetsApplication_PCL.cpp

QtWidgetsApplication_PCL::QtWidgetsApplication_PCL(QWidget *parent)
    : QMainWindow(parent)
{
   //在构造函数中为指针构造对象
    cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
	flag = 0, xb = 0, yb = 0;
	ui.setupUi(this);
     //这部分是结合QT的QVTKOpenGLNativeWidget控件和vtk显示点云的部分
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow =   vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
	view.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false));
ui.openGLWidget->setRenderWindow(view->getRenderWindow());
    view->setupInteractor(ui.openGLWidget->interactor(), ui.openGLWidget->renderWindow());
  //connect按钮和槽函数
    connect(ui.pushButton, &QPushButton::clicked, this, &QtWidgetsApplication_PCL::showCloud);
}

QtWidgetsApplication_PCL::~QtWidgetsApplication_PCL()
{}
//回调函数实现
void QtWidgetsApplication_PCL::pp_callback(const pcl::visualization::MouseEvent& event, void* args)
{
	//将类的指针传给data从而访问类的成员
	QtWidgetsApplication_PCL* data = (QtWidgetsApplication_PCL*)args;
	if (event.getButton() == pcl::visualization::MouseEvent::LeftButton && data->flag == 0) {
		data->xb = event.getX();
		data->yb = event.getY();
		qDebug() << "left button location: " << event.getX() << " " << event.getY() ;
		data->flag = 1;
	}
   //鼠标控制点云旋转实现的比较粗糙,看看就好,直接照搬vtk中鼠标事件使用
	if (event.getButton() == pcl::visualization::MouseEvent::RightButton) {

		qDebug() << "right button location: " << event.getX() << " " << event.getY() ;
		int k = 1;
		if (sqrt(pow(event.getX(), 2) + pow(event.getY(), 2)) <= 100)k = -1;
		float theta = (M_PI / 180) * k;
		Eigen::Affine3f transform = Eigen::Affine3f::Identity();
		transform.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));
		pcl::transformPointCloud(*data->cloud, *data->cloud, transform);
		data->view->removeAllPointClouds();
		data->view->addPointCloud(data->cloud, "cloud1");
	}
	if (data->flag == 1 &&
		event.getType() == pcl::visualization::MouseEvent::MouseButtonRelease)
	{
		qDebug() << "release button location: " << event.getX() << " " << event.getY();
		int xchange = event.getX() - data->xb;
		int ychange = event.getY() - data->yb;
		int changesg = abs(xchange) > abs(ychange) ? 1 : 0;
		int nchange = abs(xchange) > abs(ychange) ? xchange : ychange;
		float theta = (M_PI / 180) * nchange / 10;
		Eigen::Affine3f transform = Eigen::Affine3f::Identity();
		if (changesg)transform.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitY()));
		else transform.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitX()));
		pcl::transformPointCloud(*data->cloud, *data->cloud, transform);
		data->view->removeAllPointClouds();
		data->view->addPointCloud(data->cloud, "cloud1");
		data->flag = 0;
	}
}

//按钮控件的槽函数,点击显示点云
void QtWidgetsApplication_PCL::showCloud() {
    pcl::io::loadPCDFile("rabbit.pcd", *cloud);
    view->addPointCloud(cloud, "cloud");
    view->resetCamera();    //视角
	view->registerMouseCallback(pp_callback, this);
	
	//重新进行界面渲染,并且回调函数也被使用了,神来之笔
   view->getRenderWindow()->Render();

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中使用VTK库,可以实现VTK的可视化功能,并且可以通过Qt的事件机制来处理鼠标击事件。下面是一个简单的示例代码,演示了如何在VTK中处理鼠标左键击事件: 首先,需要在Qt中创建一个VTK窗口,并将其作为一个QWidget的子类来使用。然后,通过重写QWidget的鼠标事件函数来处理鼠标击事件。 ```cpp #include <QVTKWidget.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h> #include <vtkSmartPointer.h> #include <vtkCommand.h> class MyVTKWidget : public QVTKWidget { public: MyVTKWidget(QWidget* parent = nullptr) : QVTKWidget(parent) { // 创建VTK渲染器和交互器 renderer = vtkSmartPointer<vtkRenderer>::New(); interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); interactor->SetRenderWindow(GetRenderWindow()); GetRenderWindow()->AddRenderer(renderer); // 设置交互器样式为默认样式 interactor->SetInteractorStyle(vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New()); // 添加鼠标左键击事件监听器 vtkSmartPointer<MouseClickListener> clickListener = vtkSmartPointer<MouseClickListener>::New(); clickListener->SetVTKWidget(this); interactor->AddObserver(vtkCommand::LeftButtonPressEvent, clickListener); } private: vtkSmartPointer<vtkRenderer> renderer; vtkSmartPointer<vtkRenderWindowInteractor> interactor; class MouseClickListener : public vtkCommand { public: static MouseClickListener* New() { return new MouseClickListener; } void SetVTKWidget(MyVTKWidget* widget) { vtkWidget = widget; } virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) { if (eventId == vtkCommand::LeftButtonPressEvent) { // 处理鼠标左键击事件 vtkRenderWindowInteractor* interactor = static_cast<vtkRenderWindowInteractor*>(caller); int* pos = interactor->GetEventPosition(); // 在这里可以根据鼠标击的位置进行相应的操作 // 输出鼠标击的位置 std::cout << "Mouse left button clicked at position: " << pos[0] << ", " << pos[1] << std::endl; } } private: MyVTKWidget* vtkWidget; }; }; int main(int argc, char** argv) { QApplication app(argc, argv); // 创建一个Qt窗口 QWidget window; window.resize(800, 600); // 创建一个VTK窗口,并将其添加到Qt窗口中 MyVTKWidget vtkWidget(&window); vtkWidget.resize(800, 600); window.show(); return app.exec(); } ``` 在上述代码中,我们创建了一个名为`MyVTKWidget`的类,继承自`QVTKWidget`,并重写了鼠标事件函数`Execute`。在`MyVTKWidget`的构造函数中,我们创建了VTK渲染器和交互器,并将其与VTK窗口关联起来。然后,我们创建了一个名为`MouseClickListener`的内部类,继承自`vtkCommand`,用于处理鼠标左键击事件。在`MouseClickListener`的`Execute`函数中,我们可以根据鼠标击的位置进行相应的操作。 请注意,上述代码只是一个简单示例,实际使用时可能需要根据具体需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值