Я понимаю, как выставлять простые члены данных, создавая новый класс QObject
, у которого есть мой класс в качестве члена. Например:
class MyClass {
public:
int anInt;
};
И обертка
class MyClassQWrapped : public QObject {
Q_OBJECT
Q_PROPERTY(int anInt READ anInt write setAnInt NOTIFY anIntChanged)
public:
int anInt(){return myClass.anInt;}
void setAnInt(int value){
if(myClass.anInt==value)return;
myClass.anInt = value;
emit anIntChanged;
}
signals:
anIntChanged();
private:
MyClass myClass;
};
Но как мне обернуть объекты с помощью элементов данных указателя? Скажем, например, у меня был связанный класс списка, и я хотел разоблачить его в qml:
Class LinkedList {
public:
int anInt;
LinkedList *next;
};
Я не могу использовать тот же подход, что и выше, потому что тогда свойство оболочки будет указателем на LinkedList
, а не LinkedListQWrapped
. Если список изменен кодом, отличным от Qt, у меня нет способа узнать, какой (если есть) LinkedListQWrapped
object соответствует данному LinkedList*
.
Теперь мне позволено изменить модель c++, но я не могу позволить ей зависеть от Qt. Я могу думать о одном решении, в котором я добавляю элемент данных пользователя void*
класс c++, а затем устанавливаю его, чтобы указать на соответствующий обернутый объект, как только я создал оболочку.
Я видел подобное в box2d.
Является ли это рекомендуемым способом решения проблемы? Общепринято ли предоставлять пользователям данных void*
user в коде библиотеки, чтобы заставить их играть хорошо с различными инфраструктурами, такими как Qt? Или есть другое решение этой проблемы?
Я не верю, что вы можете выставить классы QObject
для QML для QML, поскольку единственный способ, которым я это знаю, - через QQmlContext
.
Глядя на QML box2d extentsion, кажется, что все классы QML, связанные с классами, производятся из QObject
так или иначе, посмотрите здесь box2d repo.
Тем не менее, они используют функции обертки для преобразования между типами QML box2d и обычными типами QObject
non-. т.е.
/**
* Convenience function to get the Box2DJoint wrapping a b2Joint.
*/
inline Box2DJoint *toBox2DJoint(b2Joint *joint)
{
return static_cast<Box2DJoint*>(joint->GetUserData());
}
Я просто задал аналогичные вопросы: как разоблачить C++ структуры для вычислений в Qml
Оказалось, что нет прямого пути. Но если вы посмотрите на ответ на этот вопрос, вы увидите, как мы его решили. Мы просто построили обертку и сделали все соответствующие объекты ее членами. У этих членов есть свои собственные свойства, которые они просто отправляют через обертку. Тогда вам просто нужно управлять получателем и сеттером, чтобы передать значения членам-оболочкам. Для испускания объектов из членов вы можете ввести EmitterHelperObjects (только небольшие объекты, которые наследуют QObject и чья задача состоит в том, чтобы бросать сигналы). В некоторых случаях вам может потребоваться зарегистрировать указатель обертки как MetaType. Я не понял этого, потому что, когда мне нужно это делать, а когда нет.
Итак, подытожим подход: вы не используете указатель напрямую, но получаете доступ только к свойствам своих членов, используя Wrapper как "Forwarder". Его немного печатается, но работает довольно хорошо. Лично мне не нравится эта сторона Qt/Qml, эта одна вещь One Identity в некоторых ситуациях оказывается уродливой.
Я знаю, что вы давно задали вопрос, но, возможно, это помогает другим.