Reputation: 385
I am going to write program using Qt for some image processing and I want it to be able to run in non-gui mode (daemon mode?). I'm inspired by VLC player, which is "typically" GUI program, where you can configure it using GUI, but you can also run it in non-gui
option when it runs without GUI. Then it uses some configuration file created in GUI mode.
Question is how should be such a program design? Should be some program core, which is GUI independent and depending on options it is being connected with GUI interface?
Upvotes: 7
Views: 9690
Reputation: 139
I ran into this with Qt6, 6.6.1, in a Windows docker container. My unit-test executable would fail because Qt6 could not find some Windows related GUI DLLs. Setting -platform offscreen
did not help on Windows.
This was the failure I saw:
unknown file: error: Unknown C++ exception thrown in the test fixture's constructor.
Then I used depends in console mode to profile my test executable to see the missing windows DLLs.
LoadLibraryW("Windows.UI.ViewManagement.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.UI.ViewManagement.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("Windows.UI.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.UI.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("Windows.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EF9F33C.
LoadLibraryW("Windows.dll") returned NULL. Error: The specified module could not be found (126).
LoadLibraryW("combase.dll") called from "c:\build\source\debug\platforms\QWINDOWSD.DLL" at address 0x00007FF83EFA02B0.
LoadLibraryW("combase.dll") returned 0x00007FF84B150000.
Next, I ran my test executable with the QT_LOGGING_RULES="*.debug=true"
and found this debug line from Qt:
Attempting to create platform theme "windows" via CreatePlatformTheme
This led me to QGuiApplication docs and I found I needed to set QT_QPA_PLATFORMTHEME=null
Upvotes: 0
Reputation: 21
The example by lpapp above didn't work for me, as I got
qt.qpa.screen: QXcbConnection: Could not connect to display localhost:10.0
Could not connect to any X display.
when running without an X display (any value for DISPLAY, not just localhost:10.0
).
There was a workaround - export QT_QPA_PLATFORM='offscreen'
- but that's not a command line option, your user is expected to do it, which isn't nice.
So, following posting a question here, further research lead me to the following QT5 document that explains the "approved" way to start up with or without a GUI depending on command line options:
https://doc.qt.io/qt-5/qapplication.html#details
However, your mileage may vary. The example there didn't "just work" for me, either!
I had to use the command line arg to then choose one of two methods to run. Each method created its own app object (QCoreApplication for headless, QApplication for GUI, as the docs show) and then running the app.
It may be because I'm working with "mostly Qt 4" code and compiling on Qt 5 that things are being a bit odd but this method now works, so I've not investigated further.
Upvotes: 2
Reputation: 3799
With Qt5, running a Qt application with the command line argument -platform offscreen
does draw offscreen.
See the documentation https://doc.qt.io/qt-5/qguiapplication.html#QGuiApplication
The options currently supported are the following:
-platform platformName[:options], specifies the Qt Platform Abstraction (QPA) plugin.
Overrides the QT_QPA_PLATFORM environment variable.
The supported platform names are listed in the platformName docs.
Tested with Qt 5.15.1
Upvotes: 1
Reputation: 53173
Yes, you could use a "headless" or "gui" option for the binary using QCommandLineParser. Note that it is only available from 5.3, but the migration path is pretty smooth within the major series if you still do not use that.
#include <QApplication>
#include <QLabel>
#include <QDebug>
#include <QCommandLineParser>
#include <QCommandLineOption>
int main(int argc, char **argv)
{
QApplication application(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription("My program");
parser.addHelpOption();
parser.addVersionOption();
// A boolean option for running it via GUI (--gui)
QCommandLineOption guiOption(QStringList() << "gui", "Running it via GUI.");
parser.addOption(guiOption);
// Process the actual command line arguments given by the user
parser.process(application);
QLabel label("Runninig in GUI mode");
if (parser.isSet(guiOption))
label.show();
else
qDebug() << "Running in headless mode";
return application.exec();
}
TEMPLATE = app
TARGET = main
QT += widgets
SOURCES += main.cpp
qmake && make && ./main
qmake && make && ./main --gui
Usage: ./main [options]
My program
Options:
-h, --help Displays this help.
-v, --version Displays version information.
--gui Running it via GUI.
Upvotes: 9
Reputation: 32635
You can pass an argument to your application when starting to show in gui or non-gui modes. For example if you pass -non-gui parameter when running in command line then the application should not show the main window and it should do some other stuff :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
bool GUIMode=true;
int num = qApp->argc() ;
for ( int i = 0; i < num; i++ )
{
QString s = qApp->argv()[i] ;
if ( s.startsWith( "-non-gui" ) )
GUIMode = false;
}
if(GUIMode)
{
w.show();
}
else
{
//start some non gui functions
}
return a.exec();
}
Upvotes: 4