2

私は、C++ からカスタム QML 要素を動的にインスタンス化しようとして困っています。

したがって、問題をレイアウトするには:

  • UI から抽象化された軽量のNodeオブジェクト データ構造があります。
  • 大量のメモリQObjectと派生メモリがあるため、必要に応じて UI 要素をインスタンス化する必要があります。
  • それぞれNode_ui*メンバーがあり、それぞれUI_node*メンバーがいます。
  • それぞれNodeに固有の があり_id、それぞれUIに がありID PROPERTY、 から配信され_node*ます。NodeID はインスタンス化時に設定され、変更できないため、ID プロパティは読み取り専用です。
  • QML 要素には、デフォルトのパラメーターを持つコンストラクターのみを含める必要があります。たとえば、コンストラクターに何も渡すことはできません。
  • QML 要素が作成されると、_node*メンバーはであるため、 ID プロパティにアクセスしようとするNULLQML 子要素はインスタンス化時に設定されないため、aux メソッドによってのみ設定できますが、プロパティは事実上読み取り専用の定数であり、インスタンス化後、 のメンバーが実際に設定されると更新されなくなります。UI_node*_node*UI

基本的に、QML要素にアクセスできるように、作成時Nodeにそれぞれに対応するリンクを設定できる必要がありますが、コンストラクターに渡すことはできません。プロパティは読み取り専用であるため、読み取りますインスタンス化時に、メンバーがまだであるときに 1 回だけなので、ID 値にアクセスできません。UIUIUI_node* UINULL

IDプロパティが実際には変更されず、変更できず、変更されるべきではないにもかかわらず、インスタンス化後のメンバーを設定するときに発行するNOTIFY idChanged()シグナルを追加し、IDゲッターのチェックを追加して、偽のダミーを返すことです。の場合は_node*任意の値、それ以外の場合はメンバーから ID 値をフェッチします。言うまでもなく、これはエレガントではなく、いくらかのオーバーヘッドが追加され、ダミーの ID 値はワームの可能性があるため、QML 内部の不適切な設計を無効にする方法についてのアイデアを歓迎します。_node*NULL_node*

4

3 に答える 3

1

私はちょうど解決策を思いついたのですが、かなり単純なものです。QtQuick はコンストラクターのパラメーターを指定できないように設計されていることと、「作成して設定する」アプローチが私の特定の使用シナリオに大きな影響を与えることを考慮して、UIたとえパラメータとしてそこに渡されません。

したがって、「作成して設定する」のではなく、「設定して作成する」だけで、各アイテムを作成する前に設定され、アイテム コンストラクターでデータを設定するために使用される静的クラス メンバーを使用します。

class UI : public QQuickItem
{
    Q_OBJECT
public:
    explicit UI(QQuickItem * parent = 0);
    ...
private:
    Object * object;
    static UI * rootUI;
};

Object * UI::protoObject = 0;

UI::UI(QQuickItem * parent) : QQuickItem(parent), object(protoObject) {
    if (!protoObject) qDebug() << "ERROR: prototype object is 0, unexpected";
    ...
}

そして実際のオブジェクト作成:

UI::setProtoObject(obj);
// create QQmlComponent with obj set being set in the constructor
UI::setProtoObject(0);

また、コンストラクターの早い段階でオブジェクトを設定する必要がない場合に適用できる別の方法は、QQmlComponentsを作成しbeginCreate()、必要なプロパティを設定し、でファイナライズすることですcompleteCreate()

于 2014-01-11T10:40:19.370 に答える
0

QML コンポーネントは常に特定のデータを持たない遺伝的構造であるため、インスタンス化とフィルの 2 つのステップを避けることはできません。

ui.qml

import MyModules 1.0

MyUIRoot {
    id: root

    // all the visual stuff
    Rectangle {
        Text {
            text: root.nodeId // binding should be set up automatically
        }
    }
}

次に、関数で継承するクラスをMyUIRootc++ でビルドします。myuiroot.hmyuiroot.cppQQuickItem

public:
    Q_PROPERTY(int nodeId READ nodeId NOTIFY nodeIdChanged);
    int nodeId();
    void setNode(Node* node);

signals:
    void nodeIdChanged();

private:
    Node* _node;

あなたmyuiroot.cppが持っている

MyUIRoot::MyUIRoot(QQuickItem *parent) :
    QQuickItem(parent)
{
}

int nodeId()
{
    if (_node)
        // make sure that every valid ID is > 0
        return _node.id();
    else
        return -1;
}

void setNode(Node* node)
{
    if (_node != node)
    {
        _node = node;
        emit nodeIdChanged();
    }
}

コンポーネントをmain.cpp

qmlRegisterType<MyUIRoot>("MyModules", 1, 0, "MyUIRoot");

で作成します

QQmlComponent c(_view->engine(), path);
QObject *o = c.create();
MyUIRoot *item = qobject_cast<MyUIRoot*>(o);
item.setNode(....);

C++ から視覚的な Qt Quick 要素を作成する他の唯一の方法は、視覚的な項目を作成するために QML を必要としない「カスタム シーン グラフ項目」を使用することです。http://qt-project.org/doc/qt-5.0/qtquick/qquickitem.html#custom-scene-graph-itemsを参照してください。

于 2014-01-11T01:43:35.383 に答える
0

2 番目のコンストラクターを追加し、C++ から要素を作成します

ui.h

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

class UI : public QQuickItem
{
    Q_OBJECT
public:
    explicit UI(QQuickItem *parent = 0);
    explicit UI(QQuickItem *parent = 0, Node *node = 0);

signals:

public slots:

private:
    Node* _node;

};

ui.cpp

#include "ui.h"

UI::UI(QQuickItem *parent) :
    QQuickItem(parent)
{
}

UI::UI(QQuickItem *parent, Node *node) :
    QQuickItem(parent)
  , _node(node)
{
    qDebug() << "My ID is" << node->id();
}

で作成

Node *node = new Node();
UI ui(0, node); // or parent QQuickItem instead of '0'
于 2014-01-11T10:31:54.607 に答える