如何在单例中创建QML对象?

4

我已经在MyQMLObject.qml文件中定义了一个QML对象。这个QML文件看起来像这样:

import QtQuick 2.4

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

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

应用程序启动时会动态添加文本。每种语言都有不同的文本,因此根据所选的语言,rootItem的宽度会有所变化。我希望在应用程序启动时创建MyQMLObject只需一次,甚至不用将其可视化并保存其实际宽度在单例对象中,以便我可以在代码中重复使用该值而不必再创建MyQMLObject。我该如何实现呢?
目前,我有一个单例QML文件,其中包含一个QtObject,其中包含一些常量值。我是否可以在该单例QtObject中创建MyQMLObject的实例?
我的单例Style.qml如下:
pragma Singleton

import QtQuick 2.4

QtObject {
  readonly property int maxWidth: 400
  // ...
}

你必须使用QML来计算文本大小吗? - Mitch
不一定。感谢提供替代建议! - Silex
为什么不直接使用text1.paintedWidth呢? - sk2212
@sk2212:我简化了问题,只保留了文本,但总的来说,我希望它也能在更复杂的GUI项目上运行。 - Silex
1个回答

15

首先,如果可能的话,您可以使用 Column 代替手动计算最大宽度:

MyQMLObject.qml

import QtQuick 2.4

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

您可以使用动态对象创建来创建临时的Column项:

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)
}

接下来,注册单例:

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();
}

但是需要注意的是,通过从C++计算最大宽度可以改进这种方法,从而避免构造一个只会被丢弃的项目。运用 这个例子

#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"

它使用 QFontMetrics 来计算宽度

main.qml 保持不变。


哇,谢谢你详细的回答,米奇,还有建议替代方案!我现在就试试。 - Silex
我正在阅读qmldir,因为对我来说这可能更可取。在那里,看起来您不需要使用qmlRegisterSingletonType。它可以被省略,因为我没有办法在没有它的情况下使其工作。 - tanghus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接