在同一UI中使用QVTKWidget和QOpenGLWidget
Using QVTKWidget and QOpenGLWidget in the same UI?
我正在开发一个项目,该项目使用 QOpenGLWidget
的自定义子类来显示一些渲染。在 paintGL()
方法结束时,它会调用小部件的 update()
方法来触发重绘事件(如果它可见)。现在我想向我的 Ui 添加一个额外的QVTKWidget
,我通过使用如下所示的内容来实现:
QVBoxLayout* layout = findChild<QVBoxLayout*>("layout_simulation");
QVTKWidget* widget = new QVTKWidget();
// Setup arrow
vtkSmartPointer<vtkArrowSource> arrowSource = vtkSmartPointer<vtkArrowSource>::New();
[more VTK stuff...]
widget->GetRenderWindow()->AddRenderer(renderer);
renderer->AddActor(arrowActor);
renderer->ResetCamera();
// Add widget to ui
layout->addWidget(widget);
VTK 小组件将添加到 UI 中,并按预期工作。问题是,一旦我使用 layout->addWidget()
方法,所有其他QOpenGLWidget
对象都会变黑并且不显示任何内容。此外,此黑色不是VTKRenderer
的背景色,因为即使我更改VTK小部件的背景颜色,其他小部件仍然是黑色的。我检查了一下,paintGL()
仍然在循环中被调用,但它只是不显示任何内容。我很确定我没有在我的小部件子类中使用任何糟糕的 OpenGL 代码,所以我想这与 QOpenGLWidget
和 QVTKWidget
的内部初始化有关。如果我省略所有 VTK 调用并仅添加新创建的QVTKWidget
,也会发生同样的情况。
有趣的是,如果我省略layout->addWidget()
调用,VTK 会在单独的窗口中打开渲染器,所有 OpenGL 小部件都可以正常工作。但是我当然想在我的 ui 中嵌入渲染器。
没有人有这方面的经验,或者你知道我可能遇到过的任何陷阱,或者是否有任何可能导致这种情况的常见问题?
顺便说一句:我使用OpenGL 3.3核心配置文件和自定义着色器作为我的QOpenGLWidget
子类。
编辑:我删除了对3.3核心配置文件的请求,现在它使用4.4兼容性配置文件。我想它现在使用与VTKRenderer
相同的配置文件,因此可以排除这是错误的来源。
所以我不知道究竟是什么导致了这个问题,但我解决了它。起初我发现 VTK 还有第二个小部件类叫做 QVTKWidget2
但不幸的是它与 Qt 5.4 不完全兼容,因为它使用旧的 QGL 类(如 QGLWidget
而不是 QOpenGLWidget
)。所以我开始将其重新实现为QOpenGLWidget
的子类,这非常简单。以下是我的类QVTKWidget3
的源文件,它适用于Qt 5.4,适合任何感兴趣的人。我只做了有限的测试(因为我还在学习 VTK),但做了一些简单的例子,比如展示球体作品。
再说一遍:这仅适用于Qt 5.4(测试版),因为旧版本不提供QOpenGLWidget类!
头文件: qvtkwidget3.h
#ifndef QVTKWIDGET3_H
#define QVTKWIDGET3_H
#include "vtkSmartPointer.h"
#include "vtkGenericOpenGLRenderWindow.h"
#include "vtkEventQtSlotConnect.h"
#include "QVTKInteractorAdapter.h"
#include "QVTKInteractor.h"
#include <QOpenGLWidget>
#include <QSurfaceFormat>
class QVTKWidget3 : public QOpenGLWidget
{
Q_OBJECT
public:
QVTKWidget3(QWidget *parent = NULL, Qt::WindowFlags f = 0, QSurfaceFormat format = QSurfaceFormat::defaultFormat());
virtual ~QVTKWidget3();
//! Set a custom render window
virtual void SetRenderWindow(vtkGenericOpenGLRenderWindow*);
//! Returns the curren render window (creates one if none exists)
virtual vtkGenericOpenGLRenderWindow* GetRenderWindow();
//! Returns interactor of the current render window
virtual QVTKInteractor* GetInteractor();
public slots:
//! Slot to make this vtk render window current
virtual void MakeCurrent();
//! Slot called when vtk wants to know if the context is current
virtual void IsCurrent(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data);
//! Slot called when vtk wants to frame the window
virtual void Frame();
//! Slot called when vtk wants to start the render
virtual void Start();
//! Slot called when vtk wants to end the render
virtual void End();
//! Slot called when vtk wants to know if a window is direct
virtual void IsDirect(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data);
//! Slot called when vtk wants to know if a window supports OpenGL
virtual void SupportsOpenGL(vtkObject* caller, unsigned long vtk_event, void* client_data, void* call_data);
protected:
//! Initialize handler
virtual void initializeGL();
//! Paint handler
virtual void paintGL();
//! Resize handler
virtual void resizeGL(int, int);
//! Move handler
virtual void moveEvent(QMoveEvent* event);
virtual void mousePressEvent(QMouseEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
virtual void keyPressEvent(QKeyEvent* event);
virtual void keyReleaseEvent(QKeyEvent* event);
virtual void enterEvent(QEvent*);
virtual void leaveEvent(QEvent*);
virtual void wheelEvent(QWheelEvent*);
virtual void contextMenuEvent(QContextMenuEvent*);
virtual void dragEnterEvent(QDragEnterEvent*);
virtual void dragMoveEvent(QDragMoveEvent*);
virtual void dragLeaveEvent(QDragLeaveEvent*);
virtual void dropEvent(QDropEvent*);
virtual bool focusNextPrevChild(bool);
// Members
vtkGenericOpenGLRenderWindow* m_renWin;
QVTKInteractorAdapter* m_irenAdapter;
vtkSmartPointer<vtkEventQtSlotConnect> m_connect;
private:
//! unimplemented operator=
QVTKWidget3 const& operator=(QVTKWidget3 const&);
//! unimplemented copy
QVTKWidget3(const QVTKWidget3&);
};
#endif // QVTKWIDGET3_H
源文件: qvtkwidget3.cpp
#include "qvtkwidget3.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyle.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include <QResizeEvent>
QVTKWidget3::QVTKWidget3(QWidget *parent, Qt::WindowFlags f, QSurfaceFormat format)
: QOpenGLWidget(parent, f)
, m_renWin(nullptr)
{
// VTK requires a compatibility profile
format.setProfile(QSurfaceFormat::CompatibilityProfile);
setFormat(format);
// Initialize interactors
m_irenAdapter = new QVTKInteractorAdapter(this);
m_connect = vtkSmartPointer<vtkEventQtSlotConnect>::New();
}
// Destructor
QVTKWidget3::~QVTKWidget3()
{
// Following line is not needed.
// get rid of the VTK window
// this->SetRenderWindow(NULL);
}
// GetRenderWindow
vtkGenericOpenGLRenderWindow* QVTKWidget3::GetRenderWindow()
{
if (this->m_renWin == nullptr)
{
// create a default vtk window
vtkGenericOpenGLRenderWindow* win = vtkGenericOpenGLRenderWindow::New();
this->SetRenderWindow(win);
}
return this->m_renWin;
}
// SetRenderWindow
void QVTKWidget3::SetRenderWindow(vtkGenericOpenGLRenderWindow* w)
{
// do nothing if we don't have to
if(w == this->m_renWin) {
return;
}
// unregister previous window
if(this->m_renWin != nullptr) {
this->m_renWin->Finalize();
this->m_renWin->SetMapped(0);
m_connect->Disconnect(m_renWin, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent()));
m_connect->Disconnect(m_renWin, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)));
m_connect->Disconnect(m_renWin, vtkCommand::WindowFrameEvent, this, SLOT(Frame()));
m_connect->Disconnect(m_renWin, vtkCommand::StartEvent, this, SLOT(Start()));
m_connect->Disconnect(m_renWin, vtkCommand::EndEvent, this, SLOT(End()));
m_connect->Disconnect(m_renWin, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)));
m_connect->Disconnect(m_renWin, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)));
}
// now set the window
this->m_renWin = w;
if(this->m_renWin != nullptr) {
// if it is mapped somewhere else, unmap it
this->m_renWin->Finalize();
this->m_renWin->SetMapped(1);
// tell the vtk window what the size of this window is
this->m_renWin->SetSize(this->width(), this->height());
this->m_renWin->SetPosition(this->x(), this->y());
// if an interactor wasn't provided, we'll make one by default
if(this->m_renWin->GetInteractor() == NULL)
{
// create a default interactor
QVTKInteractor* iren = QVTKInteractor::New();
iren->SetUseTDx(false);
this->m_renWin->SetInteractor(iren);
iren->Initialize();
// now set the default style
vtkInteractorStyle* s = vtkInteractorStyleTrackballCamera::New();
iren->SetInteractorStyle(s);
iren->Delete();
s->Delete();
}
// tell the interactor the size of this window
this->m_renWin->GetInteractor()->SetSize(this->width(), this->height());
m_connect->Connect(m_renWin, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent()));
m_connect->Connect(m_renWin, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)));
m_connect->Connect(m_renWin, vtkCommand::WindowFrameEvent, this, SLOT(Frame()));
m_connect->Connect(m_renWin, vtkCommand::StartEvent, this, SLOT(Start()));
m_connect->Connect(m_renWin, vtkCommand::EndEvent, this, SLOT(End()));
m_connect->Connect(m_renWin, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)));
m_connect->Connect(m_renWin, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)));
}
}
// GetInteractor
QVTKInteractor* QVTKWidget3::GetInteractor()
{
return QVTKInteractor::SafeDownCast(this->GetRenderWindow()->GetInteractor());
}
// Initialize
void QVTKWidget3::initializeGL()
{
if(this->m_renWin == nullptr) {
return;
}
this->m_renWin->OpenGLInitContext();
}
// Paint
void QVTKWidget3::paintGL()
{
vtkRenderWindowInteractor* iren = nullptr;
if(this->m_renWin != nullptr) {
iren = this->m_renWin->GetInteractor();
}
if(iren == nullptr || !iren->GetEnabled()) {
return;
}
iren->Render();
}
// Resize
void QVTKWidget3::resizeGL(int w, int h)
{
if(this->m_renWin == nullptr) {
return;
}
this->m_renWin->SetSize(w,h);
// and update the interactor
if(this->m_renWin->GetInteractor() != NULL) {
QResizeEvent e(QSize(w,h), QSize());
m_irenAdapter->ProcessEvent(&e, this->m_renWin->GetInteractor());
}
}
// Move
void QVTKWidget3::moveEvent(QMoveEvent* e)
{
QWidget::moveEvent(e);
if(this->m_renWin == nullptr) {
return;
}
this->m_renWin->SetPosition(this->x(), this->y());
}
// --------
// Slots
// --------
void QVTKWidget3::Start()
{
makeCurrent();
m_renWin->PushState();
m_renWin->OpenGLInitState();
}
void QVTKWidget3::End()
{
m_renWin->PopState();
}
void QVTKWidget3::MakeCurrent()
{
return;
// Automaticly handled by QOpenGLWidget
// this->makeCurrent();
}
void QVTKWidget3::IsCurrent(vtkObject*, unsigned long, void*, void* call_data)
{
bool* ptr = reinterpret_cast<bool*>(call_data);
*ptr = (int)true;
}
void QVTKWidget3::IsDirect(vtkObject*, unsigned long, void*, void* call_data)
{
int* ptr = reinterpret_cast<int*>(call_data);
*ptr = (int)true;
}
void QVTKWidget3::SupportsOpenGL(vtkObject*, unsigned long, void*, void* call_data)
{
int* ptr = reinterpret_cast<int*>(call_data);
*ptr = (int)true;
}
void QVTKWidget3::Frame()
{
if(m_renWin->GetSwapBuffers()) {
this->update();
}
// This callback will call swapBuffers() for us
// because sometimes VTK does a render without coming through this paintGL()
// FOLLOWING NOT TESTED FOR QOPENGLWIDGET
// if you want paintGL to always be called for each time VTK renders
// 1. turn off EnableRender on the interactor,
// 2. turn off SwapBuffers on the render window,
// 3. add an observer for the RenderEvent coming from the interactor
// 4. implement the callback on the observer to call updateGL() on this widget
// 5. overload QVTKWidget3::paintGL() to call m_renWin->Render() instead iren->Render()
}
// ----------------------
// Interaction handlers
// ----------------------
/*! handle mouse press event
*/
void QVTKWidget3::mousePressEvent(QMouseEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle mouse move event
*/
void QVTKWidget3::mouseMoveEvent(QMouseEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle enter event
*/
void QVTKWidget3::enterEvent(QEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle leave event
*/
void QVTKWidget3::leaveEvent(QEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle mouse release event
*/
void QVTKWidget3::mouseReleaseEvent(QMouseEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle key press event
*/
void QVTKWidget3::keyPressEvent(QKeyEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
/*! handle key release event
*/
void QVTKWidget3::keyReleaseEvent(QKeyEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::wheelEvent(QWheelEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::contextMenuEvent(QContextMenuEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::dragEnterEvent(QDragEnterEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::dragMoveEvent(QDragMoveEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::dragLeaveEvent(QDragLeaveEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
void QVTKWidget3::dropEvent(QDropEvent* e)
{
if(this->m_renWin)
{
m_irenAdapter->ProcessEvent(e, this->m_renWin->GetInteractor());
}
}
bool QVTKWidget3::focusNextPrevChild(bool)
{
return false;
}
- QVTKWidget在VTK 8.1中已弃用,并将在未来的版本中删除
- QVTKWidget SetRenderWindow() with PCLVisualizer Exception
- Qt Ros工作区中的QVTKWidget问题
- QT Qvtkwidget.交互器样式更改
- 如何使用QVTKWidget
- 在 QVTKWidget 渲染器中添加和删除 vtkChartXY/vtkContextView
- 在同一UI中使用QVTKWidget和QOpenGLWidget
- 如果QVTKWidget是QMainWindow的中心小部件,那么QMainMenu的行为会很奇怪
- VTK 6.1和Qt 5.3: 3D对象在QVTKWidget与不良透明度