将 QML(QQuickView) 添加到现有 UI

Posted

技术标签:

【中文标题】将 QML(QQuickView) 添加到现有 UI【英文标题】:Add QML(QQuickView) to existing UI 【发布时间】:2015-05-29 15:19:09 【问题描述】:

目前,我正在开发一个需要集成到 C++ Visual Studio 项目中的 Qt 类。

Qt 项目 - Qt 小部件应用程序。基于 Qt Creator 3.2.1 构建 (开源),基于 Qt 5.3.2。使用 Visual Studio 2013 专业,已安装 Qt 插件。

我尝试了来自互联网各地或其他 Stack 帖子的解决方案,但没有成功。我没有看到我的帖子重复,因为其他帖子没有解决我的问题。

我能够从代码运行 QML,但它在不同的窗口中启动。在第一张图片中,QML 窗口(Qt 画布)显示在我的程序 UI 上。

我需要将 QML 集成到我的程序 UI 中。如果有帮助,我可以使用QGraphicsView

简单的 QML 示例。 canvas.qml

import QtQuick 2.0
Rectangle 
    id: rectangle
    color: "red"
    width: 600
    height: 600 

【问题讨论】:

你是如何加载 QML 文件的?你在用 QQuickWidget 吗? 是的。我正在使用 QQuickWidget。 【参考方案1】:

请看一下我项目中 MVC 实现的一部分。这是一个在 Qt5.6 中可视化 QML 代码的类。希望对您有所帮助。

QmlViewBase::QmlViewBase( QWindow* parent, const std::string& qmlFilePath)

    this->m_pEngine = QQmlEnginePtr( new QQmlEngine() );
    this->m_pView = QQuickViewPtr ( new QQuickView( this->m_pEngine.get(), parent ));
    this->m_pView->setResizeMode( QQuickView::SizeRootObjectToView );
    this->m_pView->setSource( QUrl( qmlFilePath.c_str() ));
    this->m_pView->setVisible( false );
    this->m_pView->setMinimumSize(QSize(640, 480));


QmlViewBase::~QmlViewBase()

    try 
        this->m_pView.reset();
    catch(...) 

    


void QmlViewBase::show()

    this->m_pView->show();


void QmlViewBase::hide()

    this->m_pView->hide();


bool QmlViewBase::isVisible()

    return this->m_pView->isVisible();


bool QmlViewBase::close()

    return this->m_pView->close();


QObject * const QmlViewBase::getSlotsSignalsObject() const

    return reinterpret_cast<QObject* const >( this->m_pView->rootObject() );

为了管理控制器,我有具有以下实现的 Gui 导演类:

#ifndef de91_a97_4a2d_b906_01070cbfdd47
#define de91_a97_4a2d_b906_01070cbfdd47

#include "gui_director.h"
#include "utility/event_handler/event_handler.h"
#include "utility/exceptions.h"
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <map>
#include <QApplication>

template<typename ControllerId>
class GuiDirectorImpl : public GuiDirector<ControllerId>,
                        public EventHandler<
                              Event<ModelToUIParameters, ServerToClientEventType> >

public:
   typedef boost::shared_ptr<GuiDirectorImpl<ControllerId> > pointer;
   typedef boost::weak_ptr<GuiDirectorImpl<ControllerId> > weak_pointer;

public:
   virtual ~GuiDirectorImpl()
   
   
   ;
   GuiDirectorImpl(QApplication *app)
   
      m_app = app;
      m_currentActiveController.reset();
   

   virtual void addController(ControllerId controllerId,
                              Controller::pointer controller)
   
      if (isControllerExist( controllerId )) 
         BOOST_THROW_EXCEPTION( argument_error()
                                << error_description( "controller with such id already added" ) );
      

      m_idToController[controllerId] = controller;
   

   virtual void setActive(ControllerId controllerId)
   
      if (!isControllerExist( controllerId )) 
         BOOST_THROW_EXCEPTION( argument_error()
                                << error_description( "controller with such id doesn't exeist" ) );
      

      Controller::pointer oldController = m_currentActiveController;

      m_currentActiveController = m_idToController[controllerId];
      if(NULL != oldController)
      
          oldController->prepareViewToHide();
      
      m_currentActiveController->prepareViewToShow();

      m_currentActiveController->startShowView();

      if (NULL != oldController) 
         oldController->stopShowView();
      
   

   virtual void handleEvent(Event<ModelToUIParameters, ServerToClientEventType>::pointer event_)
   
      if (NULL == m_currentActiveController) 
         BOOST_THROW_EXCEPTION( error()
                                << error_description( "no active controller, cant handle event" ) );
      

      m_currentActiveController->handleEvent( event_ );
   

   virtual void quit()
   
      m_app->quit();
   

private:
   bool isControllerExist(ControllerId controllerId)
   
      typename std::map<ControllerId, Controller::pointer>::const_iterator iter = m_idToController.find( controllerId );

      if (m_idToController.end() == iter) 
         return false;
      

      return true;
   

private:
   QApplication *m_app;
   Controller::pointer m_currentActiveController;
   typename std::map<ControllerId, Controller::pointer> m_idToController;
;

#endif /* de91_a97_4a2d_b906_01070cbfdd47 */

【讨论】:

我喜欢你的方法,我认为 Qt 所谓的“MVC”更像是一个用于控件的 MVC 框架,而不是用于构建大型应用程序的通用框架。你如何处理视图之间的切换? 好吧,我有所谓的GUI导向器类。我会把它放在我的答案中。

以上是关于将 QML(QQuickView) 添加到现有 UI的主要内容,如果未能解决你的问题,请参考以下文章

使用 QQuickView 或 QQuickWidget 在 QWidget 应用程序中添加大量 QML 对象会带来性能问题

避免 QQuickView 延迟 qml 加载

如何将 Qt 鼠标事件转发到 QQuickView?

将 QQuickView 渲染到 QOpenGLFramebufferObject 时缺少对象

在 Qt5.3(mingw32) 中删除 QQuickView 的内存管理问题

带有 QQuickView 的 QML 信号 QT 插槽