[Interest] Pointers as Q_PPOPERTY

Bo Thorsen bthorsen at ics.com
Fri Oct 4 10:54:21 CEST 2013


Hi Николай Шатохин,

I saw on the list, that you got this working. But there were a bunch of 
things missing in the discussion. I have just done the same thing you 
are trying in one of our 4.8.5 based projects.

Some of this has been said, other parts haven't. I hope this is a 
complete description that should help you understand the topic.

Den 02-10-2013 16:12, Николай Шатохин skrev:
> I registered as QML Type class Ship inherited from QObject that have fields:
>
> Q_PROPERTY(Hull hull READ hull)
> Q_PROPERTY(Reactor reactor READ reactor)
> Q_PROPERTY(Shields shields READ shields)
>
> (all field classes inherited from QObject too)
>
> But in ship class I'm using this fields as pointers (Hull * hull). So,
> how to use correctly Q_Properties in this case? (I need call methods
> from this fields and catch signals from them in QML)
>
> Can I use something like this Q_PROPERTY(Hull hull READ hull)?

As already pointed out, you have to do pointers for this:

class Hull : public QObject { ... };

class Ship : public QObject {
   Q_OBJECT
   Q_PROPERTY(Hull* hull READ hull CONSTANT)
   Hull* m_hull;
public:
   Ship() : m_hull(new Hull(this)) {}
   Hull* hull() { return m_hull; }
};

The Reactor and Shields work exactly the same way.

For this to work, you have to declare the Hull, Reactor and Shields 
types to the QML engine. Something like this:

qmlRegisterUncreatableType<Hull>("MyGame", 1, 0, "Hull", "Can't be 
created.");
qmlRegisterType<Ship>("MyGame", 1, 0, "Ship");

> And then in QML:
>
> Ship
> {
>      id: ship
>      Hull
>      {
>           id: hull_indicator
>           backend: ship.hull
>      }
>
>      onDamage:
>      {
>          ship.hull.reduce(damage);
>      }
> }

You don't need the extra Hull {} declaration here. There is already a 
Hull object in your ship, the "ship.hull" you use in onDamage.

If this is about visualization, you should have a different set of 
classes, ShipView and HullView or something, that shows this:

import MyGame 1.0
Item {
   id: completeShip

   ShipView {
     anchors.fill: parent
     ship: internal.ship
   }

   HullView {
     anchors.fill: parent
     hull: internal.ship.hull
   }

   QtObject {
     id: internal

     Ship {
       id: ship
     }
   }
}

This might seem complicated at first, but you achieve one thing I find 
extremely important in QML coding: Keep your state in C++ and totally 
separated from the visualization of it.

This is a standard MVC pattern, actually. The Ship is the model, the 
completeShip is the controller and ShipView/HullView is the 
visualization. But somehow this isn't always followed when people code QML.

I hope this helps.

Bo.

-- 
Bo Thorsen, European Qt Manager, ICS
Integrated Computer Solutions. Delivering World-Class Applications
http://ics.com/services



More information about the Interest mailing list