VTK继承QVTKOpenGLWidget后,运行时出现黑屏不显示的问题
以下就是具体的一些情况:
VTK8.1以前的版本
VTK的版本一直在更新,8.1以前的代码在QT里一直用的都是QVTKWidget,这个类可以直接当控件来使用,关于他的显示所需要的其它类,renderWindow,和 render,包括交互所用到的interactor等,在界面初始化期间把这些工作都做完,界面就可以得到我们想要的。
给大家贴一块官方四视图例子的构造函数代码:
ui->view1/2/3/4 则是ui上提升的控件QVTKOpenGlWidget
QtVTKRenderWindows::QtVTKRenderWindows( int vtkNotUsed(argc), char *argv[])
{
this->ui = new Ui_QtVTKRenderWindows;
this->ui->setupUi(this);
vtkSmartPointer< vtkDICOMImageReader > reader =
vtkSmartPointer< vtkDICOMImageReader >::New();
reader->SetDirectoryName(argv[1]);
reader->Update();
int imageDims[3];
reader->GetOutput()->GetDimensions(imageDims);
for (int i = 0; i < 3; i++)
{
riw[i] = vtkSmartPointer< vtkResliceImageViewer >::New();
vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
riw[i]->SetRenderWindow(renderWindow);
}
this->ui->view1->SetRenderWindow(riw[0]->GetRenderWindow());
riw[0]->SetupInteractor(
this->ui->view1->GetRenderWindow()->GetInteractor());
this->ui->view2->SetRenderWindow(riw[1]->GetRenderWindow());
riw[1]->SetupInteractor(
this->ui->view2->GetRenderWindow()->GetInteractor());
this->ui->view3->SetRenderWindow(riw[2]->GetRenderWindow());
riw[2]->SetupInteractor(
this->ui->view3->GetRenderWindow()->GetInteractor());
for (int i = 0; i < 3; i++)
{
// make them all share the same reslice cursor object.
vtkResliceCursorLineRepresentation *rep =
vtkResliceCursorLineRepresentation::SafeDownCast(
riw[i]->GetResliceCursorWidget()->GetRepresentation());
riw[i]->SetResliceCursor(riw[0]->GetResliceCursor());
rep->GetResliceCursorActor()->
GetCursorAlgorithm()->SetReslicePlaneNormal(i);
riw[i]->SetInputData(reader->GetOutput());
riw[i]->SetSliceOrientation(i);
riw[i]->SetResliceModeToAxisAligned();
}
vtkSmartPointer<vtkCellPicker> picker =
vtkSmartPointer<vtkCellPicker>::New();
picker->SetTolerance(0.005);
vtkSmartPointer<vtkProperty> ipwProp =
vtkSmartPointer<vtkProperty>::New();
vtkSmartPointer< vtkRenderer > ren =
vtkSmartPointer< vtkRenderer >::New();
vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
this->ui->view4->SetRenderWindow(renderWindow);
this->ui->view4->GetRenderWindow()->AddRenderer(ren);
vtkRenderWindowInteractor *iren = this->ui->view4->GetInteractor();
for (int i = 0; i < 3; i++)
{
planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidget[i]->SetInteractor( iren );
planeWidget[i]->SetPicker(picker);
planeWidget[i]->RestrictPlaneToVolumeOn();
double color[3] = {0, 0, 0};
color[i] = 1;
planeWidget[i]->GetPlaneProperty()->SetColor(color);
color[0] /= 4.0;
color[1] /= 4.0;
color[2] /= 4.0;
riw[i]->GetRenderer()->SetBackground( color );
planeWidget[i]->SetTexturePlaneProperty(ipwProp);
planeWidget[i]->TextureInterpolateOff();
planeWidget[i]->SetResliceInterpolateToLinear();
planeWidget[i]->SetInputConnection(reader->GetOutputPort());
planeWidget[i]->SetPlaneOrientation(i);
planeWidget[i]->SetSliceIndex(imageDims[i]/2);
planeWidget[i]->DisplayTextOn();
planeWidget[i]->SetDefaultRenderer(ren);
planeWidget[i]->SetWindowLevel(1358, -27);
planeWidget[i]->On();
planeWidget[i]->InteractionOn();
}
vtkSmartPointer<vtkResliceCursorCallback> cbk =
vtkSmartPointer<vtkResliceCursorCallback>::New();
for (int i = 0; i < 3; i++)
{
cbk->IPW[i] = planeWidget[i];
cbk->RCW[i] = riw[i]->GetResliceCursorWidget();
riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResliceAxesChangedEvent, cbk );
riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::WindowLevelEvent, cbk );
riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResliceThicknessChangedEvent, cbk );
riw[i]->GetResliceCursorWidget()->AddObserver(
vtkResliceCursorWidget::ResetCursorEvent, cbk );
riw[i]->GetInteractorStyle()->AddObserver(
vtkCommand::WindowLevelEvent, cbk );
// Make them all share the same color map.
riw[i]->SetLookupTable(riw[0]->GetLookupTable());
planeWidget[i]->GetColorMap()->SetLookupTable(riw[0]->GetLookupTable());
//planeWidget[i]->GetColorMap()->SetInput(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap()->GetInput());
planeWidget[i]->SetColorMap(riw[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());
}
this->ui->view1->show();
this->ui->view2->show();
this->ui->view3->show();
// Set up action signals and slots
connect(this->ui->actionExit, SIGNAL(triggered()), this, SLOT(slotExit()));
connect(this->ui->resliceModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(resliceMode(int)));
connect(this->ui->thickModeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(thickMode(int)));
this->ui->thickModeCheckBox->setEnabled(0);
connect(this->ui->radioButton_Max, SIGNAL(pressed()), this, SLOT(SetBlendModeToMaxIP()));
connect(this->ui->radioButton_Min, SIGNAL(pressed()), this, SLOT(SetBlendModeToMinIP()));
connect(this->ui->radioButton_Mean, SIGNAL(pressed()), this, SLOT(SetBlendModeToMeanIP()));
this->ui->blendModeGroupBox->setEnabled(0);
connect(this->ui->resetButton, SIGNAL(pressed()), this, SLOT(ResetViews()));
connect(this->ui->AddDistance1Button, SIGNAL(pressed()), this, SLOT(AddDistanceMeasurementToView1()));
};
VTK8.1以后的版本
后续版本加入QVTKOpenGLWidget,QVTKOpenGLNativeWidget,而QVTKWidget在9.0往后的版本就不再用了,前边俩个是做了升级的,具体大家可以百度,在使用方面,这俩个可以直接在代码里new,也可以在UI里作为提升控件来使用;
这里QVTKOpenGLWidget 和 QVTKOpenGLNativeWidget都是没有renderwindow的,但是它的GetRenderWindow会自动创建,我们也可以选择手动创建vtkGenericOpenGLRenderWindow,看一下8.2源码里的实现:
//class QVTKOpenGLWidget;
vtkRenderWindow* QVTKOpenGLWidget::GetRenderWindow()
{
return this->qVTKOpenGLWindowInternal->GetRenderWindow();
}
//class vtkGenericOpenGLRenderWindow
vtkGenericOpenGLRenderWindow* QVTKOpenGLWindow::GetRenderWindow()
{
if (!this->RenderWindow)
{
// create a default vtk window
vtkNew<vtkGenericOpenGLRenderWindow> win;
this->SetRenderWindow(win);
}
return this->RenderWindow;
}
///class QVTKOpenGLWindow
void QVTKOpenGLWindow::SetRenderWindow(vtkGenericOpenGLRenderWindow* w)
{
// do nothing if we don't have to
if(w == this->RenderWindow)
{
return;
}
// unregister previous window
if(this->RenderWindow)
{
this->RenderWindow->Finalize();
this->RenderWindow->SetReadyForRendering(false);
this->RenderWindow->SetMapped(0);
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowMakeCurrentEvent,this, SLOT(MakeCurrent()));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowFrameEvent, this, SLOT(Frame()));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::StartEvent, this, SLOT(Start()));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::EndEvent, this, SLOT(End()));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowStereoTypeChangedEvent, this, SLOT(UpdateStereoType(vtkObject*, unsigned long, void*, void*)));
this->EventSlotConnector->Disconnect(this->RenderWindow, vtkCommand::WindowResizeEvent, this, SLOT(ResizeToVTKWindow()));
}
在使用时的样子:
void VTKWidget::InitWidget()
{
//注意vtkGenericOpenGLRenderWindo
//_renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
//this->SetRenderWindow(_renderWindow);
_render = vtkSmartPointer < vtkRenderer>::New();
_render->SetBackground(1, 0, 0);
this->GetRenderWindow()->AddRenderer(_render);
double pos[3] = { 0,0,0 };
this->CreatBall(pos);
}
//你也可以写成这样
void VTKWidget::InitWidget()
{
_renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
this->SetRenderWindow(_renderWindow);
_render = vtkSmartPointer < vtkRenderer>::New();
_render->SetBackground(1, 0, 0);
_renderWindow->AddRenderer(_render);
double pos[3] = { 0,0,0 };
this->CreatBall(pos);
}
容易出错的地方就是set,和 get 那里,一定是先set,后set的话他们所指向的指针就不一样了,所以在使用的时候出现黑屏不显示,检查以下是否漏掉,或者写错函数。