VTK + QT 项目:错误 LNK1169:找到一个或多个多重定义的符号
VTK + QT project: error LNK1169: one or more multiply defined symbols found
我的程序使用 VTK 和 QT 在 QT 中创建一个 DICOM 查看器 window。我正在尝试设置自定义交互器,以便我可以覆盖输入功能。创建此自定义交互器 class 后,我 运行 陷入链接器错误。我的代码如下:
FluoroViewer.h:
#ifndef FluoroViewer_H
#define FluoroViewer_H
#include <QMainWindow>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageViewer2.h>
#include "InteractorStyleImage.h"
namespace Ui {
class FluoroViewer;
}
class FluoroViewer : public QMainWindow {
Q_OBJECT
public:
explicit FluoroViewer(QWidget *parent = 0);
~FluoroViewer();
private slots:
void openDICOMFolder();
void on_loadImages_clicked();
private:
Ui::FluoroViewer *ui;
void drawDICOMSeries(std::string folderDICOM);
vtkSmartPointer<vtkDICOMImageReader> readerDICOMSeries;
vtkSmartPointer<vtkImageViewer2> imageViewerDICOMSeries;
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
vtkSmartPointer<InteractorStyleImage> interactorStyle;
};
#endif
FluoroViewer.cxx:
#include "FluoroViewer.h"
#include "ui_FluoroViewer.h"
#include <QFileDialog>
FluoroViewer::FluoroViewer(QWidget *parent) : QMainWindow(parent), ui(new Ui::FluoroViewer) {
ui->setupUi(this);
readerDICOMSeries = vtkSmartPointer<vtkDICOMImageReader>::New();
imageViewerDICOMSeries = vtkSmartPointer<vtkImageViewer2>::New();
renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
//interactorStyle = vtkSmartPointer<InteractorStyleImage>::New();
}
FluoroViewer::~FluoroViewer() {
delete ui;
}
void FluoroViewer::openDICOMFolder() {
QString folderNameDICOM = QFileDialog::getExistingDirectory(this, tr("Open DICOM Folder"), QDir::currentPath(), QFileDialog::ShowDirsOnly);
std::string folderName = folderNameDICOM.toUtf8().constData();
drawDICOMSeries(folderName);
}
void FluoroViewer::drawDICOMSeries(std::string folderDICOM) {
readerDICOMSeries->SetDirectoryName(folderDICOM.c_str());
readerDICOMSeries->Update();
imageViewerDICOMSeries->SetInputConnection(readerDICOMSeries->GetOutputPort());
ui->slider->setMinimum(imageViewerDICOMSeries->GetSliceMin());
ui->slider->setMaximum(imageViewerDICOMSeries->GetSliceMax());
//interactorStyle->SetImageViewer(imageViewerDICOMSeries);
imageViewerDICOMSeries->SetupInteractor(renderWindowInteractor);
//renderWindowInteractor->SetInteractorStyle(interactorStyle);
// SET FLUORO COLOR AND WINDOW LEVELS
imageViewerDICOMSeries->SetColorLevel(523);
imageViewerDICOMSeries->SetColorWindow(-1223);
imageViewerDICOMSeries->SetRenderWindow(ui->vtkRenderer->GetRenderWindow());
imageViewerDICOMSeries->Render();
renderWindowInteractor->Disable();
renderWindowInteractor->Start();
}
void FluoroViewer::on_loadImages_clicked() {
openDICOMFolder();
}
InteractorStyleImage.h:
#ifndef InteractorStyleImage_H
#define InteractorStyleImage_H
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
class InteractorStyleImage : public vtkInteractorStyleImage {
public:
static InteractorStyleImage* New();
vtkTypeMacro(InteractorStyleImage, vtkInteractorStyleImage);
protected:
vtkImageViewer2* imageViewer;
int currentSlice;
int minSlice;
int maxSlice;
public:
void SetImageViewer(vtkImageViewer2* imageViewerTemp);
void MoveSliceForward();
void MoveSliceBackward();
public:
virtual void OnKeyDown() {
std::string key = this->GetInteractor()->GetKeySym();
if (key.compare("Up") == 0) {
cout << "Up arrow key was pressed." << endl;
MoveSliceForward();
}
else if (key.compare("Down") == 0) {
cout << "Down arrow key was pressed." << endl;
MoveSliceBackward();
}
vtkInteractorStyleImage::OnKeyDown();
}
public:
virtual void OnMouseWheelForward() {
cout << "Scrolled mouse wheel forward." << endl;
MoveSliceForward();
//vtkInteractorStyleImage::OnMouseWheelForward();
}
public:
virtual void OnMouseWheelBackward() {
cout << "Scrolled mouse wheel backward." << endl;
if (currentSlice > minSlice) {
MoveSliceBackward();
}
//vtkInteractorStyleImage::OnMouseWheelBackward();
}
};
vtkStandardNewMacro(InteractorStyleImage);
#endif
InteractorStyleImage.cxx:
#include "InteractorStyleImage.h"
void InteractorStyleImage::SetImageViewer(vtkImageViewer2* imageViewerTemp) {
imageViewer = imageViewerTemp;
minSlice = imageViewer->GetSliceMin();
maxSlice = imageViewer->GetSliceMax();
currentSlice = minSlice;
cout << "Slicer: Min = " << minSlice << ", Max = " << maxSlice;
}
void InteractorStyleImage::MoveSliceForward() {
if(currentSlice < maxSlice) {
currentSlice += 1;
imageViewer->SetSlice(currentSlice);
imageViewer->Render();
}
}
void InteractorStyleImage::MoveSliceBackward() {
if(currentSlice > minSlice) {
currentSlice -= 1;
imageViewer->SetSlice(currentSlice);
imageViewer->Render();
}
}
FluoroViewerDriver.cxx:
#include <QApplication>
#include "FluoroViewer.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
FluoroViewer fluoroViewer;
fluoroViewer.show();
return app.exec();
}
对这个问题有什么想法吗?
这很可能是由于 vtkStandardNewMacro()。
你没有展示你是如何构建这个程序的,但我很确定 FluoroViewer 最终出现在一个翻译单元中,而 InteractorStyleImage 最终出现在另一个翻译单元中。但是,FluoroViewer #includes InteractorStyleImage.h,它定义了新函数。因此,您最终会在两个单独的对象中得到两个相同的符号,并且链接器会出错。解决方案是将 vtkStandardNewMacro() 调用行移动到实现中(*.cpp 文件)。
HTH,
米罗
我的程序使用 VTK 和 QT 在 QT 中创建一个 DICOM 查看器 window。我正在尝试设置自定义交互器,以便我可以覆盖输入功能。创建此自定义交互器 class 后,我 运行 陷入链接器错误。我的代码如下:
FluoroViewer.h:
#ifndef FluoroViewer_H
#define FluoroViewer_H
#include <QMainWindow>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageViewer2.h>
#include "InteractorStyleImage.h"
namespace Ui {
class FluoroViewer;
}
class FluoroViewer : public QMainWindow {
Q_OBJECT
public:
explicit FluoroViewer(QWidget *parent = 0);
~FluoroViewer();
private slots:
void openDICOMFolder();
void on_loadImages_clicked();
private:
Ui::FluoroViewer *ui;
void drawDICOMSeries(std::string folderDICOM);
vtkSmartPointer<vtkDICOMImageReader> readerDICOMSeries;
vtkSmartPointer<vtkImageViewer2> imageViewerDICOMSeries;
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
vtkSmartPointer<InteractorStyleImage> interactorStyle;
};
#endif
FluoroViewer.cxx:
#include "FluoroViewer.h"
#include "ui_FluoroViewer.h"
#include <QFileDialog>
FluoroViewer::FluoroViewer(QWidget *parent) : QMainWindow(parent), ui(new Ui::FluoroViewer) {
ui->setupUi(this);
readerDICOMSeries = vtkSmartPointer<vtkDICOMImageReader>::New();
imageViewerDICOMSeries = vtkSmartPointer<vtkImageViewer2>::New();
renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
//interactorStyle = vtkSmartPointer<InteractorStyleImage>::New();
}
FluoroViewer::~FluoroViewer() {
delete ui;
}
void FluoroViewer::openDICOMFolder() {
QString folderNameDICOM = QFileDialog::getExistingDirectory(this, tr("Open DICOM Folder"), QDir::currentPath(), QFileDialog::ShowDirsOnly);
std::string folderName = folderNameDICOM.toUtf8().constData();
drawDICOMSeries(folderName);
}
void FluoroViewer::drawDICOMSeries(std::string folderDICOM) {
readerDICOMSeries->SetDirectoryName(folderDICOM.c_str());
readerDICOMSeries->Update();
imageViewerDICOMSeries->SetInputConnection(readerDICOMSeries->GetOutputPort());
ui->slider->setMinimum(imageViewerDICOMSeries->GetSliceMin());
ui->slider->setMaximum(imageViewerDICOMSeries->GetSliceMax());
//interactorStyle->SetImageViewer(imageViewerDICOMSeries);
imageViewerDICOMSeries->SetupInteractor(renderWindowInteractor);
//renderWindowInteractor->SetInteractorStyle(interactorStyle);
// SET FLUORO COLOR AND WINDOW LEVELS
imageViewerDICOMSeries->SetColorLevel(523);
imageViewerDICOMSeries->SetColorWindow(-1223);
imageViewerDICOMSeries->SetRenderWindow(ui->vtkRenderer->GetRenderWindow());
imageViewerDICOMSeries->Render();
renderWindowInteractor->Disable();
renderWindowInteractor->Start();
}
void FluoroViewer::on_loadImages_clicked() {
openDICOMFolder();
}
InteractorStyleImage.h:
#ifndef InteractorStyleImage_H
#define InteractorStyleImage_H
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
class InteractorStyleImage : public vtkInteractorStyleImage {
public:
static InteractorStyleImage* New();
vtkTypeMacro(InteractorStyleImage, vtkInteractorStyleImage);
protected:
vtkImageViewer2* imageViewer;
int currentSlice;
int minSlice;
int maxSlice;
public:
void SetImageViewer(vtkImageViewer2* imageViewerTemp);
void MoveSliceForward();
void MoveSliceBackward();
public:
virtual void OnKeyDown() {
std::string key = this->GetInteractor()->GetKeySym();
if (key.compare("Up") == 0) {
cout << "Up arrow key was pressed." << endl;
MoveSliceForward();
}
else if (key.compare("Down") == 0) {
cout << "Down arrow key was pressed." << endl;
MoveSliceBackward();
}
vtkInteractorStyleImage::OnKeyDown();
}
public:
virtual void OnMouseWheelForward() {
cout << "Scrolled mouse wheel forward." << endl;
MoveSliceForward();
//vtkInteractorStyleImage::OnMouseWheelForward();
}
public:
virtual void OnMouseWheelBackward() {
cout << "Scrolled mouse wheel backward." << endl;
if (currentSlice > minSlice) {
MoveSliceBackward();
}
//vtkInteractorStyleImage::OnMouseWheelBackward();
}
};
vtkStandardNewMacro(InteractorStyleImage);
#endif
InteractorStyleImage.cxx:
#include "InteractorStyleImage.h"
void InteractorStyleImage::SetImageViewer(vtkImageViewer2* imageViewerTemp) {
imageViewer = imageViewerTemp;
minSlice = imageViewer->GetSliceMin();
maxSlice = imageViewer->GetSliceMax();
currentSlice = minSlice;
cout << "Slicer: Min = " << minSlice << ", Max = " << maxSlice;
}
void InteractorStyleImage::MoveSliceForward() {
if(currentSlice < maxSlice) {
currentSlice += 1;
imageViewer->SetSlice(currentSlice);
imageViewer->Render();
}
}
void InteractorStyleImage::MoveSliceBackward() {
if(currentSlice > minSlice) {
currentSlice -= 1;
imageViewer->SetSlice(currentSlice);
imageViewer->Render();
}
}
FluoroViewerDriver.cxx:
#include <QApplication>
#include "FluoroViewer.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
FluoroViewer fluoroViewer;
fluoroViewer.show();
return app.exec();
}
对这个问题有什么想法吗?
这很可能是由于 vtkStandardNewMacro()。 你没有展示你是如何构建这个程序的,但我很确定 FluoroViewer 最终出现在一个翻译单元中,而 InteractorStyleImage 最终出现在另一个翻译单元中。但是,FluoroViewer #includes InteractorStyleImage.h,它定义了新函数。因此,您最终会在两个单独的对象中得到两个相同的符号,并且链接器会出错。解决方案是将 vtkStandardNewMacro() 调用行移动到实现中(*.cpp 文件)。
HTH,
米罗