6

I have defined a QML object under MyQMLObject.qml. This QML file looks like this:

import QtQuick 2.4

Item {
  id: rootItem
  implicitWidth: LayoutUtils.maxImplicitWidth(children)
  implicitHeight: LayoutUtils.maxImplicitHeight(children)

  Text {
    id: text1
  }
  Text {
    id: text2
  }
  // ...
  Text {
    id: textN
  }
}

The text is added dynamically when the application starts. For each language different text is added, there for the width of the rootItem varies by the chosen language. I would like to somehow create MyQMLObject only once at application startup without even visualizing it and save its actual width in a singleton for example so I can reuse that value throughout my code without creating MyQMLObject more then once. How could I achieve this?

Right now I have a singleton QML file, which holds a QtObject which contains some constant values. Can I somehow create an instance of MyQMLObject within this singleton QtObject?

My singleton Style.qml looks like this:

pragma Singleton

import QtQuick 2.4

QtObject {
  readonly property int maxWidth: 400
  // ...
}
4
  • Do you have to use QML to calcuate the text size? Commented Feb 20, 2016 at 10:18
  • Not necessarily. Thx for the alternative suggestion! Commented Feb 20, 2016 at 14:50
  • Why not simply use text1.paintedWidth? Commented Feb 21, 2016 at 12:59
  • @sk2212: I simplified the question with having only text, but in general I want it to work on more complex GUI items also. Commented Feb 22, 2016 at 3:13

1 Answer 1

16

Firstly, if possible, you could use a Column instead of manually calculating the maximum width:

MyQMLObject.qml

import QtQuick 2.4

Column {
    Text {
        text: "blah"
    }
    Text {
        text: "blahblah"
    }
}

You can use dynamic object creation to create the temporary Column item:

Style.qml

pragma Singleton

import QtQuick 2.4

QtObject {
    readonly property int maxWidth: {
        var component = Qt.createComponent("qrc:/MyQMLObject.qml");
        if (component.status === Component.Error) {
            console.error(component.errorString());
            return 0;
        }

        return component.createObject().width;
    }
}

main.qml

import QtQuick 2.5
import QtQuick.Window 2.2

import App 1.0

Window {
    visible: true

    Component.onCompleted: print(Style.maxWidth)
}

Then, register the singleton:

main.cpp

#include <QtGui>
#include <QtQml>

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

    qmlRegisterSingletonType(QUrl("qrc:///Style.qml"), "App", 1, 0, "Style");

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

    return app.exec();
}

However, note that this approach could be improved by calculating the maximum width from C++, eliminating the need to construct an item only to throw it away. Working off this example:

#include <QtGui>
#include <QtQml>

class Style : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int maxWidth READ maxWidth CONSTANT)

public:
    Style(QObject* parent = 0) :
        QObject(parent),
        mMaxWidth(0)
    {
        QFontMetrics fontMetrics(qApp->font());
        // Here is where you'd fetch the text...
        QStringList dummyText;
        dummyText << "blah" << "blahblah";
        foreach (const QString &string, dummyText) {
            const int width = fontMetrics.boundingRect(string).width();
            if (width > mMaxWidth)
                mMaxWidth = width;
        }
    }

    int maxWidth() const
    {
        return mMaxWidth;
    }

private:
    int mMaxWidth;
};

static QObject *singletonTypeProvider(QQmlEngine *, QJSEngine *)
{

    Style *style = new Style();
    return style;
}

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

    qmlRegisterSingletonType<Style>("App", 1, 0, "Style", singletonTypeProvider);

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

    return app.exec();
}

#include "main.moc"

It uses QFontMetrics to calculate the width.

main.qml remains unchanged.

Sign up to request clarification or add additional context in comments.

2 Comments

Wow, thanks for the detailed answer Mitch and also for suggesting an alternative! Will try them out right now.
I was reading in qmldir as that for me would be preferable. There it looks like you wouldn't need to use qmlRegisterSingletonType. It could just be omitted, because I couldn't get it to work without it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.