Timer error when launching a new QGuiApplication after exit
-
Hi,
Update: It seems that not deleting the
QGuiApplication
and runningexec
on it a second time makes the error go away, so I'm going to go for that, unless this is somehow against the Qt guidelines?I am trying to sequentially launch QGuiApplications without quitting the main program. The program loads some QML, which contains a timer that will quit it and clean up the
QGuiApplication
object. After that, I would like to create a newQGuiApplication
and run it, but I am getting timer errors. Minimal example that mimics what I want to do and reproduces the error:#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlComponent> void runapp(int argc, char *argv[]) { QGuiApplication* app = new QGuiApplication(argc, argv); QQmlEngine* engine = new QQmlEngine(); QQmlContext* context = engine->rootContext(); QQmlComponent* component = new QQmlComponent(engine); QObject::connect(engine, &QQmlEngine::exit, [app](const int status) { app->quit(); }); component->setData( "import QtQuick\n" "import QtQuick.Controls\n" "ApplicationWindow {\n" " width: 200\n" " height: 200\n" " visible: true\n" " Rectangle {\n" " Text {\n" " text: \"Hello world!\"\n" " }\n" " }\n" " Timer {\n" " running: true; repeat: false\n" " onTriggered: Qt.exit(0);\n" " }\n" "}\n", QUrl()); component->create(context); app->exec(); delete component; delete engine; delete app; } int main(int argc, char *argv[]) { runapp(argc, argv); runapp(argc, argv); return 0; }
The error is:
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
If I set
repeat: true
in the QML Timer then I get a segfault instead of the above error. The problem appeared in Qt 6.4, this approach worked in the Qt 5 series and up to and including Qt 6.3. I used Qt 6.4.2 for testing, the crash happens on Linux, macOS and Windows, using both the threaded and basicQSG_RENDER_LOOP
. The error is linked to the QMLTimer
, because if I remove it and just click the close button everything works.My questions:
- Am I doing something wrong?
- Am I forgetting to clean up something after the
exec
? - Could this be a bug in Qt?
The context is the Julia QML wrapper, where this error causes test failures.
For the convenience of anyone who wants to reproduce this, here is the CMakeLists.txt file to build the above code:
project(JlQML) cmake_minimum_required(VERSION 3.16.0) set(CMAKE_MACOSX_RPATH 1) find_package(Qt6 COMPONENTS Core Gui Qml Quick REQUIRED) add_executable(main main.cpp) target_link_libraries(main PRIVATE Qt6::Core Qt6::Gui Qt6::Qml Qt6::Quick)
-
@bart_janssens I guess your design may not be right. You do not want to create two QGuiApplications which is for Qt initialization and event loops. Instead, you create only one and change your layout for different GUIs with timer.
-
@JoeCFD Thanks, but to be clear: only one
QGuiApplication
lives at once. It is not clear to me from the documentation if it's allowed to delete it and create a new one. If not, fair enough, I can adapt the design. But otherwise I think I should report a bug. -
@bart_janssens You are running Qt inside flutter code? I am not sure it will work. I guess you have to start qt from C++ code like
int main( int argc, char *argv[] )
{
} -
@JoeCFD I don't know what flutter code is, but in the Julia wrapper the call to
exec
is done in a C++ library that is loaded into Julia, so ultimately this is executed in the Juliamain
function. The particularity with this approach is that a user may not want to quit Julia between the launching of two different QML applications. -