在库中创建Qt小部件(不在main中)

时间:2017-06-09 08:35:07

标签: c++ qt openvr

我正在开发一个使用OpenVR与HTC Vive套件进行通信的C ++项目。我们的想法是开发一个带有菜单的库,该菜单将在VR环境中显示,用户可以从中更改程序的某些参数。

我正在尝试将此类菜单实现为QWidget,如official OpenVR examples所示。我的问题是,在这个项目中已经存在一个main(我有权访问但我不想干扰它),在我的代码执行之前创建并启动QApplication。

我设法创建了QWidget,但由于某些原因,它的插槽根本没有被调用。我怀疑这与我没有注册"我的QWidget在事件循环中以某种方式,但问题可能在其他地方。

简而言之,如果这就是问题,如果QApplication已经在运行,连接插槽和信号的工作原理是什么?

<小时/> 这是我的测试QWidget,非常基本。

#include "overlaywidget.h"
#include "ui_overlaywidget.h"

OverlayWidget::OverlayWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::OverlayWidget)
{
    ui->setupUi(this);
}

OverlayWidget::~OverlayWidget()
{
    delete ui;
}

void OverlayWidget::on_pushButton_clicked()
{
    QApplication::quit();
}

这是控制器,直接取自上面链接的OpenVR示例。我剥夺了一切不必要的东西

#include "openvroverlaycontroller.h"

#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <QtWidgets/QWidget>
#include <QMouseEvent>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGraphicsEllipseItem>
#include <QCursor>
#include <QObject>
#include <QMainWindow>

using namespace vr;

COpenVROverlayController *s_pSharedVRController = NULL; // I guess this makes it visibile in the global scope

COpenVROverlayController *COpenVROverlayController::SharedInstance()
{
    if ( !s_pSharedVRController )
    {
        s_pSharedVRController = new COpenVROverlayController(QApplication::instance());
    }
    return s_pSharedVRController;
}

COpenVROverlayController::COpenVROverlayController(QObject * parent)
    : BaseClass(parent)
    , m_eLastHmdError( vr::VRInitError_None )
    , m_eCompositorError( vr::VRInitError_None )
    , m_eOverlayError( vr::VRInitError_None )
    , m_strVRDriver( "No Driver" )
    , m_strVRDisplay( "No Display" )
    , m_pOpenGLContext( NULL )
    , m_pScene( NULL )
    , m_pOffscreenSurface ( NULL )
    , m_pFbo( NULL )
    , m_pWidget( NULL )
    , m_pPumpEventsTimer( NULL )
    , m_lastMouseButtons( 0 )
    , m_ulOverlayHandle( vr::k_ulOverlayHandleInvalid )
    , m_bManualMouseHandling( false )
{
}

bool COpenVROverlayController::Init()
{
    bool bSuccess = true;

    m_strName = "systemoverlay";

    QStringList arguments = qApp->arguments();

    int nNameArg = arguments.indexOf( "-name" );
    if( nNameArg != -1 && nNameArg + 2 <= arguments.size() )
    {
        m_strName = arguments.at( nNameArg + 1 );
    }

    QSurfaceFormat format;
    format.setMajorVersion( 4 );
    format.setMinorVersion( 1 );
    format.setProfile( QSurfaceFormat::CompatibilityProfile );

    m_pOpenGLContext = new QOpenGLContext();
    m_pOpenGLContext->setFormat( format );
    bSuccess = m_pOpenGLContext->create();
    if( !bSuccess )
        return false;

    // create an offscreen surface to attach the context and FBO to
    m_pOffscreenSurface = new QOffscreenSurface();
    m_pOffscreenSurface->create();
    m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );

    m_pScene = new QGraphicsScene();

    // This is where I connect to the QGraphicsScene
    connect(m_pScene, &QGraphicsScene::changed, this, &COpenVROverlayController::OnSceneChanged);

    // Loading the OpenVR Runtime
    bSuccess = ConnectToVRRuntime();

    bSuccess = bSuccess && vr::VRCompositor() != NULL;

    if( vr::VROverlay() )
    {
        std::string sKey = std::string( "sample." ) + m_strName.toStdString();

        vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay( sKey.c_str(), m_strName.toStdString().c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle);

        bSuccess = bSuccess && overlayError == vr::VROverlayError_None;
    }

    if( bSuccess )
    {
        vr::VROverlay()->SetOverlayWidthInMeters( m_ulOverlayHandle,1.5f );
        vr::VROverlay()->SetOverlayInputMethod( m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse );

        m_pPumpEventsTimer = new QTimer( this );

        // This is where I connect to the QTimer
        connect(m_pPumpEventsTimer, &QTimer::timeout, this, &COpenVROverlayController::OnTimeoutPumpEvents);
        m_pPumpEventsTimer->setInterval( 20 );
        m_pPumpEventsTimer->start();


    }
    return true;
}

// First slot, never being called
void COpenVROverlayController::OnSceneChanged( const QList<QRectF>& )
{
    /* ... code ... */
}


// Second slot, never being called
void COpenVROverlayController::OnTimeoutPumpEvents()
{
    /* ... */

}


void COpenVROverlayController::SetWidget( QWidget *pWidget )
{
    if( m_pScene )
    {
        // all of the mouse handling stuff requires that the widget be at 0,0
        // (else, the widget will still be there, but it will behave as if it's trasnlated)
        pWidget->move( 0, 0 );
        m_pScene->addWidget( pWidget );
    }
    m_pWidget = pWidget;

    m_pFbo = new QOpenGLFramebufferObject( pWidget->width(), pWidget->height(), GL_TEXTURE_2D );

    if( vr::VROverlay() )
    {
        vr::HmdVector2_t vecWindowSize =
        {
            (float)pWidget->width(),
            (float)pWidget->height()
        };
        vr::VROverlay()->SetOverlayMouseScale( m_ulOverlayHandle, &vecWindowSize );
    }

}

以下是我在我的库的其他一个类的构造函数中设置这两个的方法(只要按下应用程序的&#34; VR&#34;按钮,就会调用它当应用程序已经运行时指向。)

  OverlayWidget *pOverlayWidget = new OverlayWidget(this->getMainWindow());

  // Basicallly creates a new OverlayController and calls Init
  this->controller = COpenVROverlayController::SharedInstance();
  this->controller->Init();

  // On that same controller, sets the OverlayWidget
  this->controller->SetWidget(pOverlayWidget);

提前谢谢你, 洛伦佐

编辑:添加了相关代码。 编辑:切换到Qt5样式进行连接。它仍然可以编译和运行,但事件永远不会被调用。

0 个答案:

没有答案