QT: how to exit application and close UI - c++

I tried to use qApp->exit() to exit application and close UI. but I failed the UI is still there after qApp->exit() executed. Anyone can help to figure out why? thanks a lot.
#include "clsDownloadUpdateList.h"
#include <QApplication>
#include <qtranslator.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
translator.load("en-CN_upgrader");
qApp->installTranslator(&translator);
clsDownloadUpdateList w;
w.show();
return a.exec();
}
clsDownloadUpdateList::clsDownloadUpdateList(QWidget *parent) :
QMainWindow(parent),
_state(STOP),
ui(new Ui::clsDownloadUpdateList)
{
ui->setupUi(this);
this->setWindowTitle("GCS Upgrader");
// other code
// here comes the code to exit application
qApp->exit();
// but the UI is still there.
}

#thuga is right. The problem you have is caused by your wrong code: you call qApp->exit() before right in your constructor, where your application has not started it's message cycle yet (by a.exec()).
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
translator.load("en-CN_upgrader");
qApp->installTranslator(&translator);
clsDownloadUpdateList w; // <- you call qApp->exit() right here, before a.exec();
w.show();
return a.exec();
}

It will not help you in constructor, because of no event loop started yet.
In such case you can use QTimer::singleShot() with timeout equal zero. It will cause calling what you need when event loop started. Also it is good idea to use initialization method and check it in main:
Window w;
if ( !w.init() )
return 1;
w.show();
return a.exec();

Working code:
#include <QMetaObject>
//...
QMetaObject::invokeMethod(qApp, "quit",
Qt::QueuedConnection);
Or for widgets:
QMetaObject::invokeMethod(this, "close",
Qt::QueuedConnection);

Related

How to hide QMainWindow and show splashcreen during startup?

I am trying to hide the MainWindow of my Qt desktop app during startup, and to show a splashscreen. Both only happens after the loading phase, even though I call both splash.show() and window.hide() before the loading phase. I tried to split loading phase and constructor, but result is the same. How can I achieve both before the loading phase ?
Update 1
To display the splash screen, I had to add a call to QApplication::processEvents()
Update 2
The black window was actually not the MainWindow, but a ghost window that popped because scrollArea->setVisible(true) was called in the constructor.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPixmap pixmap(QStringLiteral(":/ressources/icons/icon.png"));
QSplashScreen splash(pixmap);
splash.show();
MainWindow window; // this loads for 5-6 seconds
a.processEvents();
window.showLoginPrompt();
splash.finish(&window);
return a.exec();
}
Based on your code and some example I could make it run like you are trying to do.
You only need to call your promptLogin function instead.
#include <QApplication>
#include <QTimer>
#include <QSplashScreen>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap("D:\\Projects\\SplashScreen\\TestSplashScreen\\splash.png"));
splash->show();
MainWindow mainWin;
QTimer::singleShot(2500, splash, SLOT(close()));
QTimer::singleShot(2500, &mainWin, SLOT(show()));
return app.exec();
}

Why QProgressDialog is shown without an explicit call to `exec()` or `show()`?

I have the following code
#include "dialog.h"
#include <QApplication>
#include <QProgressDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QProgressDialog w;
//w.show();
return a.exec();
}
The execution of this code shows a QProgressDialog UI.
I would like to have the explanation why my QProgressDialog shows up without having an exec()or show() instructions.
I have read the documentation but did not find the explanation on it.
Both constructors of QProgressDialog call QProgressDialogPrivate::init, where forceTimer : QTimer is started:
...
forceTimer = new QTimer(q);
QObject::connect(forceTimer, SIGNAL(timeout()), q, SLOT(forceShow()));
...
forceTimer->start(showTime);
The forceShow() slot in turn looks like this:
void QProgressDialog::forceShow() {
Q_D(QProgressDialog);
d->forceTimer->stop();
if (d->shown_once || d->cancellation_flag)
return;
show();
d->shown_once = true;
}
The show(); statement there is the very reason the QProgressDialog is shown on object creation.
Since it will automatically open after being constructed, follow it with a cancellation.
auto * progressDialog = new QProgressDialog{};
progressDialog.cancel();

Cant use context made by external QOpenGLWidget?

The exact crash when debugging is:
The inferior stopped because it triggered an exception.
Stopped in thread 0 by: Exception at 0x7fed96c6cda, code: 0x0000005: read access violation at: 0x0, flags=0x0.
The exception then points to this line in the below code:
if(QOpenGLContext::currentContext()->isValid())
The below code is enough to reproduce the exception for me.
Subclassing the QOpenGLWidget class and making the subclass call initializeGL() once before attempting to access context does not fix problem.
#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QDebug>
void initialize(QOpenGLWidget * renderArea)
{
renderArea->makeCurrent();
if(QOpenGLContext::currentContext()->isValid())
{
qInfo() << "Valid.";
}
}
int main(int argc, char *argv[])
{
QSurfaceFormat format;
format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
QApplication a(argc, argv);
QOpenGLWidget * glw = new QOpenGLWidget;
initialize(glw);
return a.exec();
}
I now realize the answer: You have to do all such opengl initialization AFTER the event loop starts.
A fixed code where the "MainWindow" class does all opengl initialization on receiving signal "onEventLoopStarted":
#include "mainwindow.h"
#include <QApplication>
#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QDebug>
#include <QTimer>
int main(int argc, char *argv[])
{
QSurfaceFormat format;
format.setVersion(3,3);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
QApplication a(argc, argv);
MainWindow w;
w.resize(512, 512);
w.show();
QTimer::singleShot(0, &w, SLOT(onEventLoopStarted()));
return a.exec();
//Window receives event and begins to initialize.
}

How I show application when open application again Qt

Now, I have 1 application, but I don't want to open application twice, so I using QShareMemory to detect application when open twice.
And my question is: how I show current application in screen when user open application the second ?
int main(int argc, char *argv[]) {
Application a(argc, argv);
/*Make sure only one instance of application can run on host system at a time*/
QSharedMemory sharedMemory;
sharedMemory.setKey ("Application");
if (!sharedMemory.create(1))
{
qDebug() << "123123Exit already a process running";
return 0;
}
/**/
return a.exec();
}
Thanks.
Here's another approach in pure Qt way:
Use QLocalServer and QLocalSocket to check the existence of application and then use signal-slot mechanism to notify the existing one.
#include "widget.h"
#include <QApplication>
#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString appKey = "applicationKey";
QLocalSocket *socket = new QLocalSocket();
socket->connectToServer(appKey);
if (socket->isOpen()) {
socket->close();
socket->deleteLater();
return 0;
}
socket->deleteLater();
Widget w;
QLocalServer server;
QObject::connect(&server,
&QLocalServer::newConnection,
[&w] () {
/*Set the window on the top level.*/
w.setWindowFlags(w.windowFlags() |
Qt::WindowStaysOnTopHint);
w.showNormal();
w.setWindowFlags(w.windowFlags() &
~Qt::WindowStaysOnTopHint
);
w.showNormal();
w.activateWindow();
});
server.listen(appKey);
w.show();
return a.exec();
}
But if you're using Qt 5.3 on Windows, there's a bug for QWidget::setWindowFlags and Qt::WindowStaysOnTopHint, see https://bugreports.qt.io/browse/QTBUG-30359.
Just use QSingleApplication class instead of QApplication:
https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return 0;
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
It is part of Qt Solutions: https://github.com/qtproject/qt-solutions

QT can't debug a simple dialog program:Signal received.The inferior stopped because it received a signal

I fail to debug a simple dialog program ,it alerts:
"Signal received.The inferior stopped because it received a signal
from the Operating System.Signal name:SIGSEGV.Signal
meaning:Segmentation fault"
I use MinGW4.8 and QT SDK 4.8 on windows.
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
It alerts at :
w.show();
When UI shows,it alerts,and can't continue the debug.How can I debug succefully?