这几天在学习PCL的可视化,所以我又想了一下之前QVTKWidget插件不能使用的问题,然后就按照有别于之前的思路又试了一下,没想到成功了,所以赶紧记录一下过程。
文章目录
一、问题描述
距离上一次尝试使用QVTKWidget插件已经过了一个月了,因为近期正好在学习PCL的可视化部分,所以就想着能不能实现QVTKWidget插件,接着我的笔记QT配置PCL过程记录(二)后面继续讲我这一次的思路。因为我通过cmake重新编译的VTK可以得到32位和64位的QVTKWidget插件,也就是说现在可以确定是要么是软件的问题,要么就是我代码写的有点问题。那么我在这个过程中遇到了有以下几个问题:
1、在使用32位的QVTKWidget插件时出现了下面这种情况:
2、在解决了1中的问题之后,运行程序有遇到了出现了下面的错误。
二、解决方案
2.1error LNK2019: 无法解析的外部符号×××,该符号在函数×××中被引用。
针对这个问题,我其实之前也在笔记里提到过,现在在提一遍加深印象吧。我归纳了以下几点可能会导致该问题的原因:
1>缺少库文件路径。如果我们只是添加了头文件,而没有添加其相应的库文件,这就会导致只有函数的声明而没有函数的定义,所以在链接时才会出现“无法解析外部符号”这样的错误。
2>编译器位数问题。如果不是缺少库文件路径,那么现在,我们大概可以判断的是,我们的应用程序应该已经连接上了第三方的库文件,但是他在调用某个东西的时候发生了问题。解决方案:我们可以尝试改变不同位数的编译器来测试程序,如将32位的编译器换成64位的编译器。
3>库文件本身的问题。而如果是这种情况,那就是最坏的一种情况了,因为造成这种情况的原因可能就很多了,可能是语言混用、内联函数定义在头文件中等等。如果是这种情况,那么就必须要重新编译该库文件。
总的来说,也就是我们要关注点就是“库文件”和“库文件路径”,库文件本身的问题相对来讲比较棘手可以最后考虑。
按照这种思路我又生了一个项目,如下所示:
为了保险起见,我把VTK中所有的lib文件都添加到项目中的路径中了,果然它没有在出现像“error LNK2019: 无法解析的外部符号×××,该符号在函数×××中被引用。”这样的问题了,但是它出现了新的问题。
2.2no override found for ××× 和 win是nullptr
在看到win是nullptr的第一时间我就在想可能是某个对象没有构造成功,所以导致是nullptr,还是因为近期在学习PCL的可视化这一部分,才想到了可能是之前没有初始化VTK的一些模块,所以才出现了这个错误,加上下面的这几行代码就可以运行了。
#include <vtkAutoInit.h> //初始化VTK模块
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
整个项目的代码如下:
WindowsTest.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_WindowsTest.h"
#include <vtkAutoInit.h> //初始化VTK模块
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#include<pcl/visualization/cloud_viewer.h>
#include<pcl/io/io.h>
#include<pcl/io/pcd_io.h>//pcd 读写类相关的头文件。
#include<pcl/io/ply_io.h>
#include<pcl/point_types.h> //PCL中支持的点类型头文件。
#include <pcl/features/normal_3d.h>
//#include "QVTKWidget.h"
#include <pcl/visualization/pcl_visualizer.h>
#include "vtkRenderWindow.h"
#include<iostream>//标准C++库中的输入输出类相关头文件。
#include<string>
using namespace std;
class WindowsTest : public QMainWindow
{
Q_OBJECT
public:
WindowsTest(QWidget *parent = Q_NULLPTR);
void PoinCloudShow();
private:
Ui::WindowsTestClass ui;
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer; //创建视图对象
};
WindowsTest.cpp
#include "WindowsTest.h"
WindowsTest::WindowsTest(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
void WindowsTest::PoinCloudShow()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
string filepath = "rabbit_t.pcd";
if (-1 == pcl::io::loadPCDFile(filepath, *cloud)) //打开点云文件
{
cout << "error input!" << endl;
return;
}
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
viewer->addPointCloud(cloud);
viewer->initCameraParameters();
viewer->addCoordinateSystem(1.0);
ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());
//setCentralWidget(ui.qvtkWidget);
ui.qvtkWidget->update();
}
mian.cpp
#include "WindowsTest.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
WindowsTest w;
w.show();
w.PoinCloudShow();
return a.exec();
}
运行效果:
三、64位QVTKWidget插件的使用
由于上述的实验都是使用的32位的QVTKWidget插件,那是因为只有32位的QVTKWidget插件才可以在VS中的QT Designer(UI设计器)中显示出来(详细的情况可以看QT配置PCL过程记录(二)这篇笔记),而64位的QVTKWidget插件只能在QT Designer中显示出来,在VS和QT中的UI设计器中都显示不出来。
如果我们将32位的dll文件先删去,VS中的UI设计器就会出现下面的情况:
此时Qt Designer中的情况如下所示:
那么我们应该怎样来使用64位的QVTKWidget插件呢?我的思路是:先使用Qt Designer设计出UI界面,然后让VS项目来链接我们实现设计好的UI界面。为了试验可不可以这样做我做了下面的尝试:
1、创建一个Widget项目。
2、使用Qt Designer创建了一个相同的Widget UI界面,并保存UI文件。
3、替换VS项目中的具有相同名字UI文件。
4、重新编译VS中的UI文件,让他重新生成uic_×××.h文件。
5、运行程序,效果如下所示。
我这么大费周章的去实现64位的QVTKWidget插件的使用,主要是害怕在之后的使用32位的QVTKWidget插件时会出现莫名其妙的错误,因为我的pcl是64位的,所以学会了64位QVTKWidget插件的使用也算是有个保险*~*。