Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在同一UI中使用QVTKWidget和QOpenGLWidget?_C++_Qt_Opengl_User Interface_Vtk - Fatal编程技术网

C++ 在同一UI中使用QVTKWidget和QOpenGLWidget?

C++ 在同一UI中使用QVTKWidget和QOpenGLWidget?,c++,qt,opengl,user-interface,vtk,C++,Qt,Opengl,User Interface,Vtk,我正在做一个项目,它使用一个自定义子类QOpenGLWidget来显示一些渲染。在paintGL()方法的末尾,它调用小部件的update()方法来触发一个重绘事件(如果它是可见的)。 现在,我想在我的Ui中添加一个额外的QVTKWidget,我可以使用如下方法: QVBoxLayout* layout = findChild<QVBoxLayout*>("layout_simulation"); QVTKWidget* widget = new QVTKWidget(); //

我正在做一个项目,它使用一个自定义子类
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);
QVBoxLayout*layout=findChild(“布局模拟”);
QVTKWidget*小部件=新的QVTKWidget();
//设置箭头
vtkSmartPointer arrowSource=vtkSmartPointer::New();
[更多VTK内容…]
小部件->GetRenderWindow()->添加渲染器(渲染器);
渲染器->AddActor(arrowcactor);
渲染器->重置摄影机();
//将小部件添加到ui
布局->添加小部件(小部件);
VTK小部件被添加到ui中,并按预期工作。问题是,只要我使用
layout->addWidget()
method我的所有其他
QOpenGLWidget
对象就会变成黑色,并且不显示任何内容。此外,此黑色不是
vtkrender
的背景色,因为即使我更改了VTK小部件的背景色,其他小部件仍然是黑色的。我检查后,
paintGL()。我很确定在我的小部件子类中没有使用任何不好的OpenGL代码,所以我猜这与
QOpenGLWidget
QVTKWidget
的内部初始化有关。如果省略所有VTK调用,只添加新创建的
QVTKWidget
,也会发生同样的情况

有趣的是,如果我省略
layout->addWidget()
调用,VTK会在一个单独的窗口中打开渲染器,所有OpenGL小部件都会正常工作。但我当然想在我的ui中嵌入渲染器

有没有人有过这样的经历,或者你知道我可能会遇到什么陷阱,或者有什么共同的问题可能导致这种情况

顺便说一句:我为我的
QOpenGLWidget
子类使用带有自定义着色器的OpenGL 3.3核心概要文件


编辑:我删除了对3.3核心配置文件的请求,现在它使用了4.4兼容配置文件。我猜它现在使用的是与
vtkrender
相同的配置文件,因此可以排除这是错误的来源。

因此我不知道问题的确切原因,但我解决了它。起初,我发现VTK有第二个小部件类,名为
QVTKWidget2
,但不幸的是,它与Qt5.4不完全兼容,因为它使用了旧的QGL类(比如
QGLWidget
而不是
QOpenGLWidget
)。因此,我开始将其重新实现为
QOpenGLWidget
的子类,这非常简单。下面是我的类
QVTKWidget3
的源文件,适用于Qt5.4,任何感兴趣的人都可以使用。我只做了有限的测试(因为我仍在学习VTK),但做了一些简单的示例,比如显示一个球体

同样:这只适用于Qt5.4(beta版),因为较旧版本的QOpenGLWidget不提供QOpenGLWidget类

头文件:qvtkwidget3.h

\ifndef QVTKWIDGET3\u H
#定义QVTKWIDGET3_H
#包括“vtkSmartPointer.h”
#包括“vtkGenericOpenGLRenderWindow.h”
#包括“vtkEventQtSlotConnect.h”
#包括“QVTKInteratorAdapter.h”
#包括“QVTKInteractor.h”
#包括
#包括
QVTKWidget3类:公共QOpenGLWidget
{
Q_对象
公众:
QVTKWidget3(QWidget*parent=NULL,Qt::WindowFlags f=0,QSurfaceFormat=QSurfaceFormat::defaultFormat());
虚拟的~QVTKWidget3();
//!设置自定义渲染窗口
虚拟void SetRenderWindow(vtkgenericopengelrenderwindow*);
//!返回当前渲染窗口(如果不存在,则创建一个)
虚拟vtkGenericOpenGLRenderWindow*GetRenderWindow();
//!返回当前渲染窗口的交互器
虚拟QVTKInteractor*GetInteractor();
公众时段:
//!使此vtk渲染窗口成为当前窗口的插槽
虚拟void MakeCurrent();
//!当vtk想知道上下文是否为当前上下文时调用插槽
虚拟void是当前的(vtkObject*调用者、未签名的长vtk_事件、void*客户端_数据、void*调用_数据);
//!vtk要框装窗口时调用插槽
虚空框架();
//!vtk要开始渲染时调用插槽
虚拟void Start();
//!vtk要结束渲染时调用插槽
虚空结束();
//!当vtk想知道窗口是否为直接窗口时调用插槽
虚拟void是直接的(vtkObject*调用者、未签名的长vtk_事件、void*客户端_数据、void*调用_数据);
//!vtk想知道窗口是否支持OpenGL时调用的插槽
虚拟void SupportsOpenGL(vtkObject*调用者、未签名的长vtk_事件、void*客户端数据、void*调用数据);
受保护的:
//!初始化处理程序
虚空初始化egl();
//!油漆处理工
虚空paintGL();
//!调整处理程序的大小
虚空重设gl(int,int);
//!移动处理程序
虚拟void moveEvent(QMoveEvent*事件);
虚拟无效MousePresseEvent(QMouseEvent*事件);
虚拟void mouseMoveEvent(QMouseEvent*事件);
虚拟无效mouseReleaseEvent(QMouseEvent*事件);
虚拟无效按键事件(QKeyEvent*事件);
虚拟作废keyReleaseEvent(QKeyEvent*事件);
虚拟无效事件(QEvent*);
虚拟事件(QEvent*);
虚拟无效wheelEvent(QWheelEvent*);
虚拟void contextMenuEvent(QContextMenuEvent*);
虚拟无效dragEnterEvent(QDragEnterEvent*);
虚拟无效dragMoveEvent(QDragMoveEvent*);
虚拟无效dragLeaveEvent(QDragLeaveEvent*);
虚拟void dropEvent(QDropEvent*);
虚拟bool-focusNextPrevChild(bool);
//成员
vtkGenericOpenGLRenderWindow*m_renWin;
qvtkinteratoradapter*m_irenAdapter;
VTKSmart指针m_连接;
私人:
//!未实现运算符=
QVTKWidget3常量和运算符=(QVTKWidget3常量和);
//!未执行
#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
#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;
}