How to use qmlpreview?
-
I'm on Qt
6.10.1and I use CMake to build my projects. I followed this documentation to setup my project.
When I build the project and runqmlpreview myexe, the program runs as expected, but any modifications of the QML files are not reflected in the application.
I have enabled QML debugging withtarget_compile_definitions(myexe PRIVATE QT_QML_DEBUG).What am I missing? How is
qmlpreviewsupposed to be used since this is the only documentation I can find on it? -
Your QML code is compiled into the executable, so you need to recompile after changing the code.
You can load QML from disk, without compiling it into the exe, that will require some code changes though.
-
I have also tried to have a CMake option that dictates if files are hot-reloadable or not. Here is a GitHub project where I almost managed to make that work. It is relying on the typical
Loader+QFileSystemWatcherapproach instead of using theqmlpreviewtool - and it does not fully work as expected (see this issue).@sierdzio said in How to use qmlpreview?:
You can load QML from disk, without compiling it into the exe, that will require some code changes though.
I am fully on board for code changes but I am unable to see which changes are necessary. Where can I learn how to prepare my project in order to use
qmlpreview? -
I've not really read your QML project but I believe using Loader is not the correct approach since that's different from the production code you want.
What you want is a way to point your qml code to actual files instead of qrc files and then a way to reload it.
The first can be done in CMake if you have proper QML modules. Here's a function I wrote doing that:
function (enable_qml_hotreload target) get_target_property(source_dir ${target} SOURCE_DIR) get_target_property(qmldir_content ${target} _qt_internal_qmldir_content) string(REGEX REPLACE "prefer [^\n]*" "prefer ${source_dir}/" qmldir_content "${qmldir_content}") set_property(TARGET ${target} PROPERTY _qt_internal_qmldir_content "${qmldir_content}") endfunction()Do note that this is using a internal variable so it is not guaranteed to work in the future.
What this does is changing the folder pointer to by the generated qmldir file to your local source files.
Then from I understanding qmlpreview should handle the reloading itself if you have defined
QT_QML_DEBUG. I haven't used this as I prefer to do a reload on demand via a shortcut that then callsclearSingletons,clearComponentCacheandloadFromModule. -
I've not really read your QML project but I believe using Loader is not the correct approach since that's different from the production code you want.
What you want is a way to point your qml code to actual files instead of qrc files and then a way to reload it.
The first can be done in CMake if you have proper QML modules. Here's a function I wrote doing that:
function (enable_qml_hotreload target) get_target_property(source_dir ${target} SOURCE_DIR) get_target_property(qmldir_content ${target} _qt_internal_qmldir_content) string(REGEX REPLACE "prefer [^\n]*" "prefer ${source_dir}/" qmldir_content "${qmldir_content}") set_property(TARGET ${target} PROPERTY _qt_internal_qmldir_content "${qmldir_content}") endfunction()Do note that this is using a internal variable so it is not guaranteed to work in the future.
What this does is changing the folder pointer to by the generated qmldir file to your local source files.
Then from I understanding qmlpreview should handle the reloading itself if you have defined
QT_QML_DEBUG. I haven't used this as I prefer to do a reload on demand via a shortcut that then callsclearSingletons,clearComponentCacheandloadFromModule. -
Honestly I don't know, I tried to make it work with
qmlpreviewyesterday after my message to see if it would be simple but I didn't unsterstand much.I recompiled
qmlpreviewto add more debug messages but I think I need message on the other side (the qml debug server running in the application) to get the full picture.
The window closed and re-opened itself upon a change but the change was ignored.I'll ask Qt commercial support about this. For now the manual method with your own QFileSystemWatcher or shortcut seems to be the sensible one.
-
As for your cmake / qmldir issue I'm not sure. I first tried it with a simpler CMake like this:
... qt_add_executable(appuntitled40 main.cpp ) qt_add_qml_module(appuntitled40 URI untitled40 VERSION 1.0 QML_FILES Main.qml ) ...I do use it one a more complicated project with multiple CMakeLists.txt and modules though.
-
As for your cmake / qmldir issue I'm not sure. I first tried it with a simpler CMake like this:
... qt_add_executable(appuntitled40 main.cpp ) qt_add_qml_module(appuntitled40 URI untitled40 VERSION 1.0 QML_FILES Main.qml ) ...I do use it one a more complicated project with multiple CMakeLists.txt and modules though.
@GrecKo Are you able to share
main.cppfor such setup? I am blocked on that. -
@GrecKo Are you able to share
main.cppfor such setup? I am blocked on that.@rudolflovrencic just a default generated main.cpp:
#include <QApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QApplication app(argc, argv); QQmlApplicationEngine engine; engine.loadFromModule("untitled40", "Main"); return app.exec(); } -
@rudolflovrencic just a default generated main.cpp:
#include <QApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { QApplication app(argc, argv); QQmlApplicationEngine engine; engine.loadFromModule("untitled40", "Main"); return app.exec(); }@GrecKo Don't you handle key press signals from QML and invoke
clearSingletons,clearComponentCacheandloadFromModuleinmain.cpp? That was the impression I got from post #4 where you introduced theenable_qml_hotreloadCMake function.Basically, I'm asking: how do you currently do a hot reload with a key press? Minimal working example or a bit more details would be useful since I'm a bit lost in the advice so far. I'm especially interested in your approach since you said that you maintain the same QML in production and for hot reloading:
@GrecKo said in How to use qmlpreview?:
...but I believe using Loader is not the correct approach since that's different from the production code you want.
In other words, you avoid the QML scaffolding needed for hot reloading (apart from catching the hot reload key press, I guess).