QML从C ++动态插入加载程序中的组件

时间:2014-12-22 14:34:22

标签: c++ qt qml

我已完全编辑了我的问题,因为我取得了一些进展,第一个问题尚不清楚。

我使用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文件放入加载器sourceComponent,它可以工作。 现在我想用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)

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

  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。

1 个答案:

答案 0 :(得分:1)

我已经成功了。

有屏幕处理功能:

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);  

效果很好,设计很好,代码很甜。