<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Accessing members of a class defined within another class]]></title><description><![CDATA[<p dir="auto">Hi Everyone,<br />
I've been struggling to get the "proof of concept" code at the bottom to work as I want and hoping to get some help.</p>
<p dir="auto">The use case is that I'll have a c++ back end processing raw values from an input stream and I want to access these values from the QML UI like this<br />
Text {text: qsTr("Value 1:" + backend.Value1.Value + " " + backend.Value1.Units)}<br />
Text {text: qsTr("Value 2:" + backend.Value2.Value + " " + backend.Value2.Units)}</p>
<p dir="auto">The code below is just trying to get the QML / C++ interface working before developing the backend.</p>
<p dir="auto">I also realise that each Value is being instantiated with the same values but I've been progressively working through the errors thrown during compile and execution and haven't got to sorting this bit.</p>
<p dir="auto">The code below compiles but throws "TypeError: Cannot read property 'Value' of undefined" for the two text lines in main.qml.</p>
<p dir="auto">Following this example <a href="https://doc.qt.io/qt-5/qtqml-cppintegration-topic.html" target="_blank" rel="noopener noreferrer nofollow ugc">https://doc.qt.io/qt-5/qtqml-cppintegration-topic.html</a> I can get the functionality I want for a single value when it's not a member of another class. While I could create a separate class for each value I wouldn't be following good object orientated practice particularly as I have about 60 different values to access from QML.</p>
<p dir="auto">As much as I've read the documents on Integrating QML and C++ and tried various versions of the code below, I've got no idea how to get QML to access the members of the Value class.</p>
<p dir="auto">Appreciate any help and direction.<br />
Peter</p>
<p dir="auto">backend.h</p>
<pre><code>#ifndef BACKEND_H
#define BACKEND_H

#include &lt;QObject&gt;
#include &lt;QString&gt;

class Value : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal Value READ getValue NOTIFY valueChanged)
    Q_PROPERTY(QString Units READ getUnits CONSTANT)

public:
    explicit Value(QObject *parent = nullptr);
    // Value(QString _units, qreal _scale);
    Value(QString _units, qreal _scale);

    qreal getValue();
    QString getUnits();
    void newRawValue(qreal _rawValue);

signals:
    void valueChanged();

private:
    QString units = ""; //prefer to be const
    qreal rawValue = 0;
    qreal scale = 0; //prefer to be const
};

class BackEnd : public QObject
{
    Q_OBJECT

public:
    explicit BackEnd(QObject *parent = nullptr);

    Value Value1;// = Value("km",3);
    Value Value2;// = Value("hr",4);
};

#endif // BACKEND_H
</code></pre>
<p dir="auto">backend.ccp</p>
<pre><code>#include "backend.h"

Value::Value(QObject *parent) : QObject(parent){
}
//Value::Value(QString _units, qreal _scale){
//    units = _units;
//    scale = _scale;
//}
qreal Value :: getValue(){return rawValue*scale;}

QString Value :: getUnits(){return units;}

void Value :: newRawValue(qreal _rawValue){
    rawValue = _rawValue;
    emit valueChanged();
}

BackEnd::BackEnd(QObject *parent) : QObject(parent){
}
</code></pre>
<p dir="auto">main.cpp</p>
<pre><code>#include &lt;QGuiApplication&gt;
#include &lt;QQmlApplicationEngine&gt;

#include "backend.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType&lt;BackEnd&gt;("io.qt.examples.backend", 1, 0, "BackEnd");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
</code></pre>
<p dir="auto">main.qml</p>
<pre><code>import QtQuick 2.12
import QtQuick.Window 2.12

import io.qt.examples.backend 1.0

Window {
    visible: true
    width: 640
    height: 480

    BackEnd {id: backend}

    Text {text: qsTr("Value 1:" + backend.Value1.Value + " " + backend.Value1.Units)}
    Text {text: qsTr("Value 2:" + backend.Value2.Value + " " + backend.Value2.Units)}
}

</code></pre>
]]></description><link>https://forum.qt.io/topic/146060/accessing-members-of-a-class-defined-within-another-class</link><generator>RSS for Node</generator><lastBuildDate>Mon, 02 Nov 2026 09:57:38 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/146060.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 28 Jun 2023 05:53:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Tue, 04 Jul 2023 08:51:02 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/grecko">@<bdi>GrecKo</bdi></a> Thanks for that it does make sense.</p>
<p dir="auto">You are correct that value1 &amp; 2 pointers never change. In the actual use case there will be other unexposed backend methods that update Value's rawValue which is then scaled to real units for the QML layer to read. All of Value's exposed methods and properties will be only be read by the QML layer. There will be exposed backend methods that are written to by the QML layer and other values that will be exposed in a model, but this is straight forward as there's plenty of information out there on doing that.</p>
<p dir="auto">Can you please confirm your recommended changes to the code I previously posted. My understanding of the changes is below but that throws a "cannot convert 'QVariant' to 'Value*' in assignment." during the build.</p>
<pre><code>class BackEnd : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Value* value1 READ getValue1 CONSTANT)
    Q_PROPERTY(Value* value2 READ getValue2 CONSTANT)
public:
    explicit BackEnd(QObject *parent = nullptr);

   QVariant getValue1(){return QVariant::fromValue(value1);}
   QVariant getValue2(){return QVariant::fromValue(value2);}
</code></pre>
<p dir="auto">When I change the Q_PROPERTY lines to below everything works</p>
<pre><code> Q_PROPERTY(QVariant value1 READ getValue1 CONSTANT)
</code></pre>
<p dir="auto">Thanks again for your assistance!</p>
]]></description><link>https://forum.qt.io/post/763537</link><guid isPermaLink="true">https://forum.qt.io/post/763537</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Tue, 04 Jul 2023 08:51:02 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Mon, 03 Jul 2023 11:35:36 GMT]]></title><description><![CDATA[<p dir="auto">Q_INVOKABLE leads to worse QML code here.</p>
<p dir="auto">Semantically, Value1 and Value2 are properties of your Backend.<br />
Invokable function are for functions, stuff that mutates your state or compute something, that's not the case here.</p>
<p dir="auto">If the Value1 and Value2 pointers never change, expose them as Q_PROPERTY in Backend.h:</p>
<p dir="auto"><code>Q_PROPERTY(Value* value1 READ getValue1 CONSTANT)</code><br />
If for some reason you don't want to register the <code>Value</code> type, you don't have to use QVariant, you can expose it as a <code>Q_PROPERTY(QObject*, ...</code></p>
<p dir="auto">Keep your getters as is and just delete the <code>Q_INVOKABLE</code> part.</p>
<p dir="auto">QML code would then be:</p>
<pre><code>Text {text: qsTr("Value 1: " + backend.value1.value + " " + backend.value1.units)}
Text {y: 20;text: qsTr("Value 2: " + backend.value2.value + " " + backend.value2.units)}
</code></pre>
<p dir="auto">Which can be rewritten with a Column and a repeater:</p>
<pre><code>Column {
    Repeater {
        model: [backend.value1, backend.value2]
        delegate: Text {
            text: qsTr("Value %1: %2 %3 ").arg(index).arg(modelData.value).arg(modelData.units)
            padding: 8
    }
}
</code></pre>
<p dir="auto">And then depending on the actual usecase you might consider exposing your values in a model instead of named properties for each Value1, Value2</p>
]]></description><link>https://forum.qt.io/post/763431</link><guid isPermaLink="true">https://forum.qt.io/post/763431</guid><dc:creator><![CDATA[GrecKo]]></dc:creator><pubDate>Mon, 03 Jul 2023 11:35:36 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Mon, 03 Jul 2023 09:28:43 GMT]]></title><description><![CDATA[<p dir="auto">After almost turning software problems into a hardware problem a few times, I finally got it to work as I intended.</p>
<p dir="auto">With the addition of Q_INVOKABLE as suggested by @J-Hilk and the removal of the Value(QObject *parent) constructor, it all works.</p>
<p dir="auto">Final code for prosperity below:<br />
backend.h</p>
<pre><code>#ifndef BACKEND_H
#define BACKEND_H

#include &lt;QObject&gt;
#include &lt;QString&gt;
#include &lt;QVariant&gt;


class Value : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal value READ getValue NOTIFY valueChanged)
    Q_PROPERTY(QString units READ getUnits CONSTANT)

public:
    Value(QString _units, qreal _scale);
    ~Value();

    qreal getValue() const;
    QString getUnits() const;
    void newRawValue(qreal _rawValue);

signals:
    void valueChanged();

private:
    const QString units;
    qreal rawValue = 1;
    const qreal scale;
};

class BackEnd : public QObject
{
    Q_OBJECT

public:
    explicit BackEnd(QObject *parent = nullptr);

    Q_INVOKABLE QVariant getValue1(){return QVariant::fromValue(value1);}
    Q_INVOKABLE QVariant getValue2(){return QVariant::fromValue(value2);}

private:
    Value *value1 = new Value("km",3);
    Value *value2 = new Value("hr",4);
};

#endif // BACKEND_H
</code></pre>
<p dir="auto">backend.cpp</p>
<pre><code>#include "backend.h"

Value::Value(QString _units, qreal _scale): units(_units), scale(_scale){}

Value::~Value(){}

qreal Value :: getValue() const {return rawValue*scale;}

QString Value :: getUnits()const {return units;}

void Value :: newRawValue(qreal _rawValue){
    if(rawValue == _rawValue)
        return;

    rawValue = _rawValue;
    emit valueChanged();
}

BackEnd :: BackEnd(QObject *parent) : QObject(parent){
}
</code></pre>
<p dir="auto">main.cpp</p>
<pre><code>#include &lt;QGuiApplication&gt;
#include &lt;QQmlApplicationEngine&gt;

#include "backend.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType&lt;BackEnd&gt;("backend", 1, 0, "BackEnd");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}
</code></pre>
<p dir="auto">main.qml</p>
<pre><code>import QtQuick 2.12
import QtQuick.Window 2.12

import backend 1.0

Window {
    visible: true
    width: 640
    height: 480

    BackEnd {id: backend}

    Text {text: qsTr("Value 1: " + backend.getValue1().value + " " + backend.getValue1().units)}
    Text {y: 20;text: qsTr("Value 2: " + backend.getValue2().value + " " + backend.getValue2().units)}
}
</code></pre>
]]></description><link>https://forum.qt.io/post/763422</link><guid isPermaLink="true">https://forum.qt.io/post/763422</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Mon, 03 Jul 2023 09:28:43 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Mon, 03 Jul 2023 09:04:29 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/jeremy_k">@<bdi>jeremy_k</bdi></a> Thanks for the advice.</p>
]]></description><link>https://forum.qt.io/post/763418</link><guid isPermaLink="true">https://forum.qt.io/post/763418</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Mon, 03 Jul 2023 09:04:29 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Sat, 01 Jul 2023 11:08:17 GMT]]></title><description><![CDATA[<p dir="auto">This is strictly practical advice. If this is an intellectual exercise, please ignore. All sorts of interesting things happen when the rules aren't followed.</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/_-peter-_">@<bdi>_-Peter-_</bdi></a> said in <a href="/post/762986">Accessing members of a class defined within another class</a>:</p>
<blockquote>
<pre><code>Q_PROPERTY(qreal Value1.Value READ Value1.getValue NOTIFY Value1.valueChanged)
</code></pre>
</blockquote>
<p dir="auto">In QML, not solely of custom, <code>.</code> is a token separator, and a token starting with an upper-case letter is a type.</p>
<p dir="auto"><a href="https://doc.qt.io/qt-6/qtqml-documents-definetypes.html#naming-custom-qml-object-types:" target="_blank" rel="noopener noreferrer nofollow ugc">https://doc.qt.io/qt-6/qtqml-documents-definetypes.html#naming-custom-qml-object-types:</a></p>
<blockquote>
<p dir="auto">It must begin with an uppercase letter.</p>
</blockquote>
<p dir="auto">Ignoring this leads to headaches. If the goal is working code rather than exploring the limits of the framework, do not use <code>.</code>  or strings starting with upper case letters in property names.</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/_-peter-_">@<bdi>_-Peter-_</bdi></a> said in <a href="/post/762821">Accessing members of a class defined within another class</a>:</p>
<blockquote>
<p dir="auto">backend.h</p>
<pre><code>[...]
</code></pre>
<p dir="auto">backend.ccp</p>
<pre><code>[...]
</code></pre>
</blockquote>
<p dir="auto">Only tangentially connected, but defining separate .h, .cpp, and main.cpp files for an example makes the code harder to follow for a forum post. My not at all humble opinion is that everything should be inlined to focus on compilation units rather than files.</p>
]]></description><link>https://forum.qt.io/post/763258</link><guid isPermaLink="true">https://forum.qt.io/post/763258</guid><dc:creator><![CDATA[jeremy_k]]></dc:creator><pubDate>Sat, 01 Jul 2023 11:08:17 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Thu, 29 Jun 2023 10:57:28 GMT]]></title><description><![CDATA[<p dir="auto">@J-Hilk Doh! M)</p>
<p dir="auto">Now I get a "static assertion failed" during compile and directed to use the Q_DECLARE_METATYPE macro.</p>
<p dir="auto">Will read the docs for the Q_DECLARE_METATYPE macro.</p>
]]></description><link>https://forum.qt.io/post/763004</link><guid isPermaLink="true">https://forum.qt.io/post/763004</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Thu, 29 Jun 2023 10:57:28 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Thu, 29 Jun 2023 10:02:15 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/_-peter-_">@<bdi>_-Peter-_</bdi></a> said in <a href="/post/762984">Accessing members of a class defined within another class</a>:</p>
<blockquote>
<p dir="auto">"incomplete type 'QVariant'</p>
</blockquote>
<p dir="auto">you should know this!</p>
<p dir="auto"><code>#include &lt;QVariant&gt;</code></p>
]]></description><link>https://forum.qt.io/post/762988</link><guid isPermaLink="true">https://forum.qt.io/post/762988</guid><dc:creator><![CDATA[J.Hilk]]></dc:creator><pubDate>Thu, 29 Jun 2023 10:02:15 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Thu, 29 Jun 2023 09:54:50 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/grecko">@<bdi>GrecKo</bdi></a> I had given that a go but got the parse warning " Warning: Property declaration Value1 has no READ accessor function or associated MEMBER variable. The property will be invalid." and compiling ends.</p>
<p dir="auto">I tried to a few different variations but got the same error.</p>
<pre><code>class BackEnd : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal Value1.Value READ Value1.getValue NOTIFY Value1.valueChanged)
    Q_PROPERTY(QString Value1.Units READ Value1.getUnits CONSTANT)
    Q_PROPERTY(qreal Value2.Value READ Value2.getValue NOTIFY Value2.valueChanged)
    Q_PROPERTY(QString Value2.Units READ Value2.getUnits CONSTANT)

public:
    explicit BackEnd(QObject *parent = nullptr);

    Value Value1;// = Value("km",3);
    Value Value2;// = Value("hr",4);
};
</code></pre>
]]></description><link>https://forum.qt.io/post/762986</link><guid isPermaLink="true">https://forum.qt.io/post/762986</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Thu, 29 Jun 2023 09:54:50 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Thu, 29 Jun 2023 09:35:52 GMT]]></title><description><![CDATA[<p dir="auto">@J-Hilk Thanks for the response. When I add the line in I get the errors "incomplete result type 'QVariant' in function definition" and "incomplete type 'QVariant' named in nested name specifier"</p>
<pre><code>class BackEnd : public QObject
{
    Q_OBJECT

public:
    explicit BackEnd(QObject *parent = nullptr);

    Q_INVOKABLE QVariant getValue1(){return QVariant::fromValue(Value1);}
    Value Value1();// = Value("km",3);
    Value Value2;// = Value("hr",4);
};
</code></pre>
]]></description><link>https://forum.qt.io/post/762984</link><guid isPermaLink="true">https://forum.qt.io/post/762984</guid><dc:creator><![CDATA[_-Peter-_]]></dc:creator><pubDate>Thu, 29 Jun 2023 09:35:52 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Wed, 28 Jun 2023 14:08:16 GMT]]></title><description><![CDATA[<p dir="auto">Your bakend object doesn't have any exposed properties named <code>Value1</code> and <code>Value2</code>.<br />
Use Q_PROPERTY to expose them like you did in your <code>Value</code> class.</p>
]]></description><link>https://forum.qt.io/post/762903</link><guid isPermaLink="true">https://forum.qt.io/post/762903</guid><dc:creator><![CDATA[GrecKo]]></dc:creator><pubDate>Wed, 28 Jun 2023 14:08:16 GMT</pubDate></item><item><title><![CDATA[Reply to Accessing members of a class defined within another class on Wed, 28 Jun 2023 06:34:40 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/_-peter-_">@<bdi>_-Peter-_</bdi></a> thats so not possible, because your Value class is not a trivial type.<br />
I think if you would fully register the class with the meta system  you might have more luck accessing the direct member. But, the far easier option would be the following:</p>
<pre><code>public:
    explicit BackEnd(QObject *parent = nullptr);

    QINVOKABLE QVariant getValue1() {return QVariant::fromValue(Value1);} 
    Value Value1;// = Value("km",3);
    Value Value2;// = Value("hr",4)
</code></pre>
<pre><code>Text {text: qsTr("Value 1:" + backend.getValue1().Value + " " + backend.getValue1().Units)}
</code></pre>
]]></description><link>https://forum.qt.io/post/762828</link><guid isPermaLink="true">https://forum.qt.io/post/762828</guid><dc:creator><![CDATA[J.Hilk]]></dc:creator><pubDate>Wed, 28 Jun 2023 06:34:40 GMT</pubDate></item></channel></rss>