我一直都想把vtk显示这一块做成一个封装的静态lib,然后别的类只需要我暴露出的头文件和lib文件就可以了,这次我实现的是对一个放stl文件的文件夹下的stl文件做显示,用的是vs2017+qt,实现的主要效果如下:
因为qt自身带的标题栏显示有点单调,我们这里使用了自定义标题栏。
stl模型主要是这样被显示的:
封装的代码:
#pragma once
#include <vtkAutoInit.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSTLReader.h>
#include <vtkSmartPointer.h>
#include <QVTKWidget.h>
#include <QtWidgets/QWidget>
#include <QtWidgets/qpushbutton.h>
#include <QtWidgets/qlayout.h>
#include <QtWidgets/qlabel.h>
#include <QtGui/qevent.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#pragma once
class STLVTK : public QWidget
{
Q_OBJECT
public:
STLVTK(QWidget *parent = nullptr);
~STLVTK();
void OpenSTLFiles(QString stlfolder);
void STLShow();
private:
void initWidget();
QVTKWidget* m_vtkWidget = nullptr;
QPoint m_dragPosition;
QPushButton *m_closeButton = nullptr;
QLabel *m_mainContent = nullptr;
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
};
对外只有两个函数,一个是显示一个是指定文件夹下模型路径
#include "STLVTK.h"
#include <QtWidgets/qfiledialog.h>
#include <vtkCornerAnnotation.h>
#include <vtkTextProperty.h>
#include <vtkTextActor.h>
STLVTK::STLVTK(QWidget *parent)
: QWidget(parent)
{
initWidget();
}
STLVTK::~STLVTK()
{}
void STLVTK::OpenSTLFiles(QString stlfolder){
QDir dir(stlfolder);
QStringList stlFiles = dir.entryList(QStringList() << "*.stl", QDir::Files);
for (int i = 0; i < stlFiles.size(); ++i) {
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName(dir.filePath(stlFiles[i]).toStdString().c_str());
reader->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
// 计算合适的位置布局
int numRows = std::ceil(std::sqrt(stlFiles.size()));
int numCols = std::ceil((float)stlFiles.size() / numRows);
double width = 1.0 / numCols;
double height = 1.0 / numRows;
double xIndex = i % numCols;
double yIndex = i / numCols;
renderer->SetViewport(xIndex * width, (numRows - yIndex - 1) * height, (xIndex + 1) * width, (numRows - yIndex) * height);
m_vtkWidget->GetRenderWindow()->AddRenderer(renderer);
}
#if 0
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
reader->SetFileName(stlfolder.toStdString().c_str());
reader->Update();
//将source转换成mapper
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
//送入渲染引擎进行显示
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
//渲染
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->SetBackground(.0, .0, .0);
//设置渲染窗口
vtkSmartPointer<vtkRenderWindow> window = vtkSmartPointer<vtkRenderWindow>::New();
m_vtkWidget->SetRenderWindow(window);
m_vtkWidget->GetRenderWindow()->AddRenderer(renderer);
#endif
}
void STLVTK::STLShow()
{
this->show();
}
void STLVTK::initWidget()
{
setWindowFlags(Qt::FramelessWindowHint);
QHBoxLayout* hlayout1 = new QHBoxLayout;
QHBoxLayout* hlayout2 = new QHBoxLayout;
m_mainContent = new QLabel;
m_mainContent->setStyleSheet("background-color: rgb(0, 0, 139);");
m_mainContent->setFixedHeight(50);
m_closeButton = new QPushButton;
m_closeButton->setObjectName("CloseButton");
m_closeButton->setStyleSheet("QPushButton {"
"background-image:url(:/sysButton/sysbutton/close.png);"
"background-repeat: no-repeat;"
"background-position: center;"
"}");
QLabel* label = new QLabel(QString::fromLocal8Bit("预览打印"));
label->setStyleSheet("color: #FDF5E6;");
hlayout1->addWidget(label);
hlayout1->addStretch();
hlayout1->addWidget(m_closeButton);
m_mainContent->setLayout(hlayout1);
m_mainContent->setMargin(0);
connect(m_closeButton, &QPushButton::clicked, this, &QWidget::hide);
QWidget *widget = new QWidget();
widget->setObjectName("modelwidget");
widget->setStyleSheet("#modelwidget {"
"background-image:url(:/BackGround/background/center_bg.png);"
"}");
m_vtkWidget = new QVTKWidget;
m_vtkWidget->setFixedSize(1300, 800);
hlayout2->addWidget(m_vtkWidget);
widget->setLayout(hlayout2);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->setMargin(3);
mainLayout->addWidget(m_mainContent);
mainLayout->addWidget(widget);
setLayout(mainLayout);
this->setStyleSheet("background-color: rgb(250, 255, 250)");
}
void STLVTK::mousePressEvent(QMouseEvent * event){
if (event->button() == Qt::LeftButton)
{
m_dragPosition = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
}
void STLVTK::mouseMoveEvent(QMouseEvent * event)
{
if (event->buttons() == Qt::LeftButton)
{
move(event->globalPos() - m_dragPosition);
event->accept();
}
}