-1

I have the following main.qml file:

import QtQuick 2.5
import QtQuick.Controls 1.4

Item
{
    anchors.centerIn: parent

    Label
    {
        id: textLabel
        anchors.fill: parent
        x: 200
        y: 400
    }

    CustomObject
    {
        id: customObjectId
    }
}

CustomObject is a QML file defined in an external binary resource, generated by the rcc command:

rcc -binary -o redTheme.qrc redTheme.rcc

CustomObject.qml

import QtQuick 2.5
import QtQuick.Controls 1.4

Item
{
    Rectangle
    {
        width: 200
        height: 120
        color: "blue"
        Label
        {
            text: "customObject"
        }
    }
}

In the C++ side, I register my resource like this:

QResource::registerResource(QCoreApplication::applicationDirPath() + "/data/themes/redTheme.rcc");

The function returns true, which means the file is opened.

Yet, CustomObject does not exist in my main.qml file. Why?

CustomObject is not a type

EDIT: I've wrapped CustomObject into a QML Module and then compiled it into a .rcc file (it means the qmldir file is inside the .qrc). No difference whatsoever, CustomObject still isn't recognized as a type, even if I add an import statement (import redTheme 1.0). Content of my qmldir file:

module redTheme
CustomObject 1.0 CustomObject.qml
Grégoire Borel
  • 1,880
  • 3
  • 33
  • 55
  • Possible duplicate of [Dynamically change QML theme at runtime](http://stackoverflow.com/questions/36335481/dynamically-change-qml-theme-at-runtime) – Grégoire Borel Apr 06 '16 at 16:17

2 Answers2

1

I am not 100% sure, but I think QML files as types only works for "internal" QML files, that is the QML files that are in the internal resource file.

In order for external QML files to work as types, you need to have a valid QML module defined, with its qmldir file and such. It may also be possible to expose it as a type using the C++ API, but I haven't investigated it, basically, it is what the qmldir file parser does.

The other way to use external QML files is as path/url, that is, if you want it instantiated, you either need to use a Loader or manually instantiate it dynamically.

This might help to register external QML files as QML types:

int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)

This function registers a type in the QML system with the name qmlName, in the library imported from uri having the version number composed from versionMajor and versionMinor. The type is defined by the QML file located at url. The url must be an absolute URL, i.e. url.isRelative() == false.

Normally QML files can be loaded as types directly from other QML files, or using a qmldir file. This function allows registration of files to types from C++ code, such as when the type mapping needs to be procedurally determined at startup.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • I intend to create a lot of themes which will be switchable at the user's will (example: user clicks on a button which switches between the blue theme and the red theme.) Thus, I don't think using `qmlRegisterType` is a good idea since I will end up with dozens/hundreds of additional lines of code. I could integrate my `CustomObject` into a `QML Module`, but it is already inside a `.qrc` file. Isn't that a bit redundant? – Grégoire Borel Mar 29 '16 at 14:41
  • Well, either you want to use a QML file as a typr or you don't which is it? In your code this is what you try to do, and registering a type is the only way to do it, either manually or with a `qmldir` file. As for the rest, it really depends what you mean by themes - just different dimensions and colors, or completely different UI structure? – dtech Mar 29 '16 at 14:46
  • Currently it's only dimensions and colors. I'll try with QML Module solution and keep you updated. – Grégoire Borel Mar 29 '16 at 14:58
  • See updated original post. Doesn't seem to work. Should I externalize my qmldir? – Grégoire Borel Mar 29 '16 at 15:27
  • @GrégoireBorel - a module will not work in a resource file, it needs to be out on the file system, also it needs to be in a valid import path, you can add import paths with `void QQmlEngine::addImportPath(const QString &path)`. But if it is only colors and dimensions, you can put a style in a simple json file, no need for anything fancy. – dtech Mar 29 '16 at 15:43
  • `QQmlEngine::addImportPath(const QString &path)` would force me to write the absolute paths of every themes in my **main.cpp** file. Since I don't want to compile my themes with my binary, I would have to copy them into my binary folder. Then, I would use `addImportPath`, but it would not be very flexible. Unless I can import all the themes with one statement? Would you mind give more information about the `JSON` style sheet? – Grégoire Borel Mar 29 '16 at 16:05
  • Or maybe have all your themes in a dedicated themes folder? It is not a JSON style sheet, just a JSON file with values for colors and dimensions, you can extra and apply to your UI files. There is nothing built in, you have to do it yourself. – dtech Mar 29 '16 at 16:24
  • This thread might be a duplicate with my other one (in which I give a solution to the whole problem): http://stackoverflow.com/questions/36335481/dynamically-change-qml-theme-at-runtime/36399339#36399339 – Grégoire Borel Apr 04 '16 at 12:13
0

I've encountered a similar effect with external rcc files. Try adding 'qrc' scheme to your url when loading qml files from external resources:

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