I am trying to show a QSplashScreen before launching my application. The problem I have is that the QSplashScreen disappears too quickly. I would like it to show for 2 seconds before the real application loads.
Below the small example I built to show the error:
#include <QApplication>
#include <QSplashScreen>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap(":/dredgingSplash.png"));
splash->show();
Qt::Alignment topRight = Qt::AlignRight | Qt::AlignTop;
splash->showMessage(QObject::tr("Setting up the main window..."), topRight, Qt::white);
QTimer::singleShot(2500, splash, SLOT(close()));
MainWindow w;
QTimer::singleShot(2500, &w, SLOT(show()));
splash->showMessage(QObject::tr("loading modules..."), topRight, Qt::white);
splash->showMessage(QObject::tr("Establishing Connections..."), topRight, Qt::white);
w.show();
delete splash;
return a.exec();
}
EDITS using QSplashScreen::finish() from official documentation:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap(":/dredgingSplash.png"));
splash->show();
Qt::Alignment topRight = Qt::AlignRight | Qt::AlignTop;
splash->showMessage(QObject::tr("Setting up the main window..."), topRight, Qt::white);
MainWindow w;
splash->showMessage(QObject::tr("loading modules..."), topRight, Qt::white);
splash->showMessage(QObject::tr("Establishing Connections..."), topRight, Qt::white);
w.show();
splash->finish(&w);
return a.exec();
}
EDITS 2 using a class:
#include <QApplication>
#include <QSplashScreen>
#include <QTimer>
class ShowImageTime {
public:
void slInit();
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSplashScreen *splash = new QSplashScreen;
splash->setPixmap(QPixmap(":/dredgingSplash.png"));
splash->show();
Qt::Alignment topRight = Qt::AlignRight | Qt::AlignTop;
splash->showMessage(QObject::tr("Setting up the main window..."), topRight, Qt::white);
MainWindow w;
QTimer::singleShot(3000, splash, SLOT(close()));// close splash after 4s
QTimer::singleShot(3000, &w, SLOT(ShowImageTime::slInit(this->show)));// mainwindow reappears after 4s
splash->showMessage(QObject::tr("loading modules..."), topRight, Qt::white);
splash->showMessage(QObject::tr("Establishing Connections..."), topRight, Qt::white);
w.show();
splash->finish(&w);
return a.exec();
}
I tried to play with the QTimer as I thought that could be the potential problem due to priority of loading, but unfortunately if I change QTimer::singleShot(2500, splash, SLOT(close())); with QTimer::singleShot(12500, splash, SLOT(close())); or even higher numbers, there is literally no difference, so I am not sure why that is not an option.
Also I came across this source and I also followed official documentation but that also did not help me to figure out the problem.
Also this post suggests that the problem keeps being related to the QTimer but I don't see how since bigger or smaller intervals seems not to count.
What am I missing to keep the QSplashScreen to stay for 2 seconds instead of disappearing (or not even see it) right away?
Thanks for pointing to the right direction.
The problem is, that your code is starting the timer and then continues running. So the MainWindow is created, shown and the SplashScreen is deleted/finished. The timer's timout function will trigger after all this happened. That is why it closes so quickly.
SplashScreens are usually shown, if the application start is very slow, because there is so much going on in the background. In your case, there is basically no load and the code executes super quick.
You could either use a sleep call for 2sec right after calling splash->show() or put all the code for closing the SplashScreen, showing the Mainwindow in a timer's timout slot and delete the SplashScreen there.
Related
I have an embedded Qt application for Linux which has the following startup code:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
QQuickView AppView;
AppView.setSource(QUrl(QStringLiteral("main.qml")));
AppView.resize(480, 800);
AppView.show();
return app.exec();
}
I'd like to remove the black screen shown before AppView and to display QML animation
instead of it.
I see two possible options here but non of them is clear. Could you please advice
which one of them is more correct and also comment/answer the questions in each.
Option 1: To display QSplashScreen at the beginnning of main().
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSplashScreen *splash = new QSplashScreen();
splash->show();
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
}
The question here is what API to use to attach QML animation to QSplashScreen?
QSplashScreen inherits from QWidget, and so as I understand, no API like QQuickWidget::setSource() can be used.
Option 2: To display another QQuickView at the beginnning of main() with attached QML animation.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQuickView SplashView;
SplashView.setSource(QUrl(QStringLiteral("SplashScreen.qml")));
SplashView.resize(480, 800);
SplashView.show();
app.exec();
// Startup actions neeeded to display AppView correctly
// Black screen is shown for several seconds
// ...
QQuickView AppView;
AppView.setSource(QUrl(QStringLiteral("main.qml")));
AppView.resize(480, 800);
AppView.show();
}
The question here is how to to close the SplashView and to display AppView on top of it?
Thanks
Option 1 is not good idea. You should not mix Qt Quick and Qt Widgets applications.
QApplication::exec() starts event loop of main gui thread and never returns until application is quit. Although I do not like your way of handling splash screen, in this case, you can use something like this.
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl("SplashScreen.qml"));
view.resize(640, 480);
view.show();
QTimer::singleShot(2000,&view,[&view](){
view.close();
view.setSource(QUrl("main.qml"));
view.show();
});
return app.exec();
I used timer to simulate "actions to display app correctly" . You should replace that part with your class, which does actions. When actions are done that class can emit a signal in receiving slot you can close current view which shows splash screen and show main app.
Thank you for going through this post. I have searched forums,blogs and SO, but could not get what I actually need.
I am experimenting on how to display multiple mainwindows. I am using a embedded hardware board. I have successfully ported QT lib on to it.
I have written a small program.
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow text_plane;
text_plane.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
text_plane.setStyleSheet("background-color: Black;");
text_plane.show();
a.exec();
return a.exec();
}
The above code displays one window only.
Even if I create a Mainwindow w1 after text_plane.show() like
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow text_plane,w1;
text_plane.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
text_plane.setStyleSheet("background-color: Black;");
text_plane.show();
w1.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
w1.setStyleSheet("background-color: Yellow;");
w1.show();
a.exec();
return a.exec();
}
Now only the w1 window is shown. What about the text_plane window ?? how to get that back.
Can anyone help me out here to make this understand.
Thank you
First of all, I wonder, what are you trying to achieve here:
a.exec();
return a.exec();
You need to call this method only once, you know.
Second of all, both of your windows are shown (you can see it in a taskbar), but, since you set Qt::FramelessWindowHint, one of them is drawn on top of the other. You can split them by using move (or something like it):
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w, w1;
w.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
w.setStyleSheet("background-color: Black;");
w.show();
w1.setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
w1.setStyleSheet("background-color: Yellow;");
w1.show();
w.move(0, 0);
w1.move(100, 100);
return app.exec();
}
How do I have the user first login before getting to the main window in my QT app? I'm new to QT and have looked through the documentation and have not found anything very helpful. Thank you.
I would make this in the following way. Let's assume, that my login dialog is a QDialog:
class Login : public QDialog
{
[..]
};
In my application, I create an instance of my Login dialog and if it is accepted, i.e. closed with OK button, I open my main window:
int main(int argc, char *argv[])
{
[..]
QMainWindow mw;
Login login;
if (login.exec() == QDialog::Accepted) {
mw.show();
}
[..]
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
LoginWindow l; // create login-widget
connect(&l, SIGNAL(loggedIn), &w, SLOT(show()); // connect to mainwindow show()
l.show(); // show login-window instead of
// mainwindow at start
return a.exec();
}
You might want to :
1 - exec the loop only if the dialog is accepted, otherwise you application continues to run
2 - create the mainwindow only if accepted, cause it might be a heavy interface, which takes time to initialize
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog_Login dialog;
if(dialog.exec() == QDialog::Accepted){
MainWindow w;
w.setUser(dialog.GetUser());
w.show();
return a.exec();
}
else return 0;
}
You need to create the QApplication instance in parrallel with the login dialog.
I'm trying to create an exit button that correctly closes the GUI I have made in QT. I have tried doing this in the following way:
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
int window_width = QApplication::desktop()->width();
int window_height = QApplication::desktop()->height();
MainWindow w;
QPushButton * quit_btn = new QPushButton;
quit_btn->setParent(w.centralWidget());
quit_btn->setGeometry(window_width-50,12,32,32);
QObject::connect(quit_btn,SIGNAL(clicked()),qApp,SLOT(quit()));
w.resize(window_width,window_height);
w.show();
return a.exec();
}
Unfortunately when I push the button, the debugger gives an error:
Invalid address specified to RtlFreeHeap( 003E0000, 0028F950 )
Can anybody point me in the right direction?
Connect the button's clicked() signal to your main window's close() slot. That way things are cleaned up properly.
I'm just starting out with Qt on a Mac and working through:
http://doc.qt.nokia.com/4.7/gettingstartedqt.html
When I run the second example which has the following code:
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
The application starts up fine and works fine. The only issue occurs when I click the "Quit" button. When I do that the crash reporter is invoked and osx says the app quit unexpectedly.
Anything obvious I'm doing wrong?
Thanks
The problem is the order of the delete if you declare variables on the stack. The best it to give your object parents so that they can destroy the children.
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWidget window;
// If window get's destroyed, it will destroy it's children...
QTextEdit textEdit(&window);
QPushButton quitButton("Quit",&window);
QObject::connect(&quitButton, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
window.setLayout(&layout);
window.show();
return app.exec();
}
PS: Did you actually try a debugger to see where it crashes? It will give you an idea ;) My suggestion is to take a working Qt example and play with it.
PS2: The order I created the widgets also prevents the crash...
Try:
QTextEdit * textEdit = new QTextEdit;
QPushButton * quitButton = new QPushButton("Quit");