VTK + QT项目:错误LNK1169:找到一个或多个多重定义的符号

时间:2016-01-07 22:09:20

标签: c++ visual-studio qt linker-errors vtk

我的程序正在使用VTK和QT在QT窗口内创建DICOM查看器。我正在尝试设置自定义交互器,以便我可以覆盖输入函数。在创建此自定义交互器类时,我遇到了链接器错误。我的代码如下:

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();
}

关于这个问题的任何想法?

1 个答案:

答案 0 :(得分:1)

这很可能是由于vtkStandardNewMacro()。 你没有展示如何构建这个程序,但我很确定FluoroViewer最终会在一个翻译单元中,InteractorStyleImage在另一个翻译单元中。但是,FluoroViewer #include InteractorStyleImage.h,它定义了New函数。因此,您最终会在两个单独的对象中使用两个相同的符号,并且链接器会缩小。解决方案是将vtkStandardNewMacro()调用行移动到实现(* .cpp文件)中。

HTH,

米罗