2017-08-03 54 views
0

是否有可能在運行時從C++創建ObjectModel?在運行時從C++創建ObjectModel

我有一個基於插件的應用程序,其中每個插件創建QQmlComponent和設置信號和槽然後給該組件到主應用程序用於呈現在ListView,對於該端我想有在c一個ObjectModel ++側並在那裏操縱它。

main.qml(主要的應用程序接口):

import QtQuick 2.9 
import QtQuick.Layouts 1.3 
import QtQuick.Controls 2.2 


ApplicationWindow { 
    id: qmlMainWindow 
    width: 1240 
    height: 720 
    minimumWidth: 270+600 
    minimumHeight: 120+400 
    visibility: "Maximized" 
    visible: true 
    title: "CTC - Tableau de bord" 

    GridLayout { 
     anchors.fill: parent 
     columnSpacing: 0 
     rowSpacing: 0 
     columns: 2 
     rows: 2 
     HeaderArea { 
      id: headerArea 
      Layout.row: 0 
      Layout.columnSpan: 2 
      Layout.fillWidth: true 
      Layout.fillHeight: true 
      Layout.minimumHeight: 120 
      Layout.maximumHeight: 120 
     } 
     NotificationArea { 
      id: notificationArea 
      Layout.row: 1 
      Layout.column: 1 
      Layout.fillHeight: true 
      Layout.maximumWidth: 350 
      Layout.preferredWidth: 300 
      Layout.minimumWidth: 270 
      model: notificationModel 
     } 
     MainArea { 
      id: mainArea 
      bgColor: "lightgray" 
      Layout.row: 1 
      Layout.column: 0 
      Layout.fillWidth: true 
      Layout.fillHeight: true 
     } 
    } 

} 

MAINAREA項目:

import QtQuick 2.9 
import QtQuick.Controls 2.2 
import QtQuick.Layouts 1.3 
import QtQml.Models 2.1 

Item { 
    objectName: "mainArea" 

    function addReport(obj) { 
     omodel.append(obj); 
    } 

    property alias bgColor: mainAreaBackground.color 
    property ObjectModel omodel 
    Rectangle { 
     id: mainAreaBackground 
     anchors.fill: parent 
     color: "white" 
     ListView { 
      anchors.fill: parent 
      model: omodel 
     } 
    } 
} 

在第一次嘗試,我想從C++側訪問MAINAREA項目,並呼籲與QQuickItem的addReport功能*從插件返回,沒有運氣。

main.cpp中:

#include <QGuiApplication> 
#include <QQmlApplicationEngine> 
#include <QQmlContext> 
#include <QTimer> 
#include <QtPlugin> 
#include <QPluginLoader> 
#include <QDebug> 
#include <QtQmlModel> 

#include "notificationmodel.h" // model used in the notification area 
#include "interfaces/inotification.h" // interface for a plugin 
#include "interfaces/ireport.h" // interface for a plugin (of interest for this post) 

int main(int argc, char *argv[]) 
{ 
    QGuiApplication::setApplicationName("ctc_dashboard"); 
    QGuiApplication::setOrganizationName("CTC"); 
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    QGuiApplication a(argc, argv); 

    NotificationModel notificationModel(&a); 

    QQmlApplicationEngine engine; 

    QPluginLoader ploader; // I load the plugin which his task is to connect 
          // to a QtRemoteObject on some server and create a QQuickItem 
          // which will present some statistics. 
    ploader.setFileName("plugins/affair_states/AffairStates.dll"); 

    engine.rootContext()->setContextProperty("notificationModel", &notificationModel); 

    engine.load(QString("%1/%2") 
       .arg(QGuiApplication::applicationDirPath()) 
       .arg("qml/main.qml")); 
    if (engine.rootObjects().isEmpty()) 
     return -1; 

    if(ploader.load()){ 
     IReports* plugin = qobject_cast<IReports*>(ploader.instance()); 
     if(plugin) { 
      qDebug() << "Good plugin : " << plugin->name(); 
      QObject::connect(plugin, &IReports::notify, [&](NotificationModel::Notification n){ 
       notificationModel.addNotification(n); 
      }); 
      QObject::connect(plugin, &IReports::newReport, [&](QQuickItem* i){ 
       qInfo() << "Signal recived"; 
       qDebug() << "New report " << i; 
       qInfo() << engine.rootContext()->contextObject()->findChild<QObject*>("mainArea"); 
       qInfo() << "Omodel " << engine.rootContext()->contextProperty("omodel"); 
      }); 
     } 
    } 

    return a.exec(); 
} 

iReport的插件接口:

#include <QtPlugin> 

#include "inotification.h" 
#include <QQuickItem> 

class IReports: public INotification 
{ 
    Q_OBJECT 
public: 
    IReports(); 
    virtual ~IReports(); 

    virtual QList<QQuickItem*> reports() = 0; 
    virtual QString name() const = 0; 
    virtual QString sectionName() const = 0; 

signals: 
    void newReport(QQuickItem* report); 

}; 
#define IReports_iid "dz.ctc.dashboard.interfaces.IReports" 
Q_DECLARE_INTERFACE(IReports, IReports_iid) 

Main app screenshoot

+0

那麼如何定義ObjectModel?它究竟來自哪裏? – dtech

+0

它來自[Qt庫](http://doc.qt.io/qt-5/qml-qtqml-models-objectmodel.html)它是一個渲染其對象的標準模型。在我的情況下,我想渲染一些從應用程序插件發出的qquickitems。 –

+0

我的意思是它在插件的權利?你爲什麼要使用普通圖書館?有專門針對QML提供的'QQmlExtensionPlugin'顧名思義。 – dtech

回答

1

It is possible to create any QML object from C++,雖然99.99%病例是不好的做法,你不應該做,以及錯誤設計的指示,這些設計很可能會在稍後回來咬你。

應該創建或操作QML從C++對象,你應該是暴露於QML使QML對象可以與它交互的明確定義的C++接口。

無論你打算做什麼,最有可能有更好的方法來做到這一點。向我們展示一些代碼,以便我們可以給你一個更具體的答案。

+0

我編輯了文本並添加了一些代碼,希望它能幫助您清楚地看到問題。 –