Issue: Qt Creator can't find custom C++ QtQuick Components, but compilation still works
-
I'm following the Integrating QML and C++ example in Qt Creator 4.13.3, using Qt version 5.15.2. I followed all the instructions exactly. The app builds and runs correctly.
However, QT Creator itself somehow isn't aware of the component I added:
This is an issue for me.Things I Have Tried
-
Using QML Emulation Layer from selected qt
Nothing happened except for having to fix this unrelated bug (via user Jaehak Lee's suggestion in the responses).
-
Cleaning and rebuilding everything.
No change.
-
Following this solution from StackOverflow.
It does not seem to be applicable - it assumes that I have a
modules
directory under my source directory but I'm not sure why I would have that, nor why I would need to useqmlplugindump
directly with Qt 5.15.2.However, I did try it regardless, to no avail:
Information that might help
This is how I have tried to set up qmltypes:
QT += quick bluetooth CONFIG += c++14 CONFIG += qmltypes QML_IMPORT_NAME = me.tague.myproject QML_IMPORT_MAJOR_VERSION = 1
This is the header file for the component I am trying to add:
#ifndef HOMECONTROLLER_H #define HOMECONTROLLER_H #include <QObject> #include <qqml.h> #include <QtBluetooth> #include "locateddevice.h" class HomeController : public QObject { Q_OBJECT Q_PROPERTY(LocatedDevice* deviceList READ deviceList NOTIFY deviceListChanged) QML_ELEMENT public: explicit HomeController(QObject *parent = nullptr); LocatedDevice* deviceList(); private: LocatedDevice *m_deviceList; QBluetoothDeviceDiscoveryAgent *m_agent; signals: void deviceListChanged(); }; #endif // HOMECONTROLLER_H
-
-
I've developed a hackish workaround - if you're frustrated by this issue too, this "fix" is ugly but might help in the short-term:
I noticed that Qt Creator still recognizes the old
qmlRegisterType
function calls if they're invoked frommain
in a project. So naturally, I made a custom compiler step forqmake
that generates a header file with allQML_ELEMENT
-tagged classes registered in a function.First, make sure you've set up
qmltypes
in your project as usual - yourQML_IMPORT_NAME
and all that is set.Add to the bottom of
MyProject.pro
:type_registrar_unfucker.name = type_registrar_unfucker type_registrar_unfucker.input = TYPE_REGISTRAR_SOURCES type_registrar_unfucker.commands = python3 $$PWD/type_unfuck.py ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} $$QML_IMPORT_NAME $$QML_IMPORT_MAJOR_VERSION type_registrar_unfucker.output = ${QMAKE_FILE_IN_BASE}.h type_registrar_unfucker.clean = ${QMAKE_FILE_IN_BASE}.h type_registrar_unfucker.variable_out = HEADERS QMAKE_EXTRA_COMPILERS += type_registrar_unfucker TYPE_REGISTRAR_SOURCES += $$OUT_PWD/myproject_metatypes.json
Add as
type_unfuck.py
in your source directory:# type unfuck # ----------- # This python script deals with the issue of Qt Creator not being able to recognize element types # registered using 'QML_ELEMENT'. # # It does so by generating a header, 'myprojectname_metatypes.h'. # Include this header ONLY in main.cpp, and then call `registerTypes()` first thing in `main`. # Then, Qt Creator will stop whining. import sys import json source_path = sys.argv[1] dest_path = sys.argv[2] import_name = sys.argv[3] import_major = sys.argv[4] with open(source_path) as f: data = json.load(f) includes = ["QtQml"] types = [] for file in data: includes.append(file["inputFile"]) for type in file["classes"]: if "classInfos" in type and {"name":"QML.Element","value":"auto"} in type["classInfos"]: types.append(type["className"]) with open(dest_path, 'w') as f: for i in includes: f.write(f'#include <{i}>\n') f.write('void registerTypes() {\n') for t in types: f.write(f'\tqmlRegisterType<{t}>("{import_name}", {import_major}, 0, "{t}");\n') f.write('}\n')
Then, just add
#include <myproject_metatypes.h>
to your project'smain.cpp
and invokeregisterTypes();
immediately in yourmain
function. Build your project, then click on Tools -> QML/JS -> Reset Code Model, and Qt Creator should now recognize your custom components correctly.