QML 从C++在加载器中动态插入组件

QML Dynamic insertions of components in loader from C++

本文关键字:动态 插入 组件 加载 C++ QML      更新时间:2023-10-16

自从我取得了一些进展以来,我已经完全编辑了我的问题,第一个不清楚。

我使用Qt 4.8和QtQuick 1.0。

我有一个页面,我需要保留上边距和下边距。所以我定义了一个这样的 Main.qml

Item  {
    id: salesWindow
    width: 800
    height: 600
[...] //Properties def
TopBar {[...]}
CloseButton{[...]}
Rectangle {[...]}
//I want to load qml file in this loader. The QML file loaded use some of the Main.qml properties
Loader {
    id: appPlaceHolder
    objectName: "loader"
    anchors.centerIn: parent
 }
Rectangle {[...]}
BotBar {[...]}
}

如果我将 qml 文件放入加载器源组件中,它可以工作。现在我想用C++来做,而且设计得很好。我在 SalesAppDisplay.h 中有子类 QDeclarativeComponent。

class SalesAppDisplay : public IDisplayScreen
{
  Q_OBJECT
  static const std::string QML_FILENAME;
  static const std::string QML_DIR_PATH;
public:
  SalesAppDisplay(DisplayContext& context, QDeclarativeEngine& engine, QObject* parent = 0);
  ~SalesAppDisplay();
  void doScreenInit();
  const std::string getQmlFilename() const;    
};
class IDisplayScreen : public QDeclarativeComponent
{
  Q_OBJECT
[...]
}

和负责组件实例化的 Ctor

IDisplayScreen::IDisplayScreen(DisplayContext& context, QDeclarativeEngine& engine, std::string     qmlFilepath, QObject* parent)
: QDeclarativeComponent(&engine, QString(qmlFilepath.c_str()), parent)

我想从 main 将我的组件插入到 QML 中,而不是通过更改源代码在加载器中加载 qml 文件.cpp :

  m_view.setSource(QUrl::fromLocalFile("../displaymanager/rsrc/qml/Main.qml"));
  QObject* mainObj = m_view.rootObject();
  [ .. Set file property ]
  //this is the component subclass instantiation (made by factory)
  m_currentScreen = displaymanager::createDisplayScreen(IDisplayScreen::SALESAPP, *(m_context), *(m_view.engine()), mainObj);
  QDeclarativeItem* saleAppObj = qobject_cast<QDeclarativeItem*>(m_currentScreen->create(m_view->rootContext()));
  saleAppObj->setParentItem(qobject_cast<QDeclarativeItem*>(mainObj));
  [ .. Set file property ]
  //I can find my loader without any problems
  QDeclarativeItem *loader = mainObj->findChild<QDeclarativeItem*>("loader");
  /* I don't know what to do here for making it works */
  m_view.show();
  m_qApp.exec();

我已经尝试了loader->setProperty("sourceComponent", qobject_cast<QVariant>(saleAppObj));,以及其他一些类似的技巧,但没有任何结果。

我的 saleApp.qml 有错误,说他不知道我在其中使用的 Main.qml 属性(他显然在组件实例化处加载)。尽管main.qml被完美加载,但SaleApp.qml中没有任何内容出现。

我已经让它工作了。

有屏幕处理功能:

void QtDisplayManager::switchScreen(int screenID)
{
  if(m_currentScreen)
  {
    m_currentScreen->destroyItem();
  }
  //App screen creation
  m_currentScreen = displaymanager::createDisplayScreen(screenID, m_context, *m_engine, m_mainObj);
  //Get App placehoder 
  QDeclarativeItem* loaderItem = m_mainObj->findChild<QDeclarativeItem*>("loader");
  //Put app in placeholder
  if(loaderItem)
  {
    m_currentScreen->getItem()->setParentItem(loaderItem);
    m_engine->clearComponentCache();
    m_context.setcurrentDisplayID(screenID);
  }
}

destroyItem() 是我添加的一个函数,用于删除项目指针而不删除整个组件,只是因为我遇到了一个问题,即添加新组件时组件未从视图中删除。

SalesApp.qml在MainWindow.qml上没有引用,所以我添加了两个包装器:

m_view.rootContext()->setContextProperty("managerWrapper", this);
m_view.rootContext()->setContextProperty("appWrapper", m_currentScreen);  

完美工作,设计很好,代码很甜蜜。