Qt - Non Modal Dialog before Main Window is created - c++

I've been struggling to do this : I want to show on a window a QWidget, or a QDialog before the MainWindow is created, but I cannot use exec() because it will enter its loop and won't create my MainWindow before I accept or reject the dialog.
The reason I want to do this is to have a widget showing information while the MainWindow constructs itself. I don't want to keep this extra window once the MainWindow is showing up.
I believe the issue comes from the fact that the main window is already created when a.exec() is called and the window won't show up before a.exec(). The solution I found is to use a QDialog instead and call exec() but it blocks the rest of the code which I don't want to happen.
Code :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
StartUpDialog start; //this is my custom QDialog, can be a QWidget if necessary.
qDebug() << "starting up!";
MainWindow w;
start.exec(); //I tried show() but it won't show up.
w.startApp(&start); //this function will do some stuff.
w.show();
//I don't want start to stay after mainwindow shows up
return a.exec();
}
Here is what I tried so far :
I tried to create and show the StartUpDialog while constructing the MainWindow but it won't work out.
Use start.show(), but it won't show before the mainwindow does, both for a QWidget and a QDialog.
Use start.exec(), this does what I want but it's modal and I couldn't make it non-modal with SetModal(false) or setWindowModality(Qt:NonModal).
I also tried to use start.exec() and attempted to reimplement accepted() and exec() so that it automatically calls accepted() as soon as it appears but it will still close the window.
Hopefully you can help me in that issue, and thanks for reading !
UPDATE : Solved thanks to Trap, here is how I made it :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
StartUpDialog start;
QSplashScreen *splash = new QSplashScreen();
StartUpWidget *start = new StartUpWidget(splash);
splash->resize(350,380);
start->show();
splash->raise();
splash->show();
qDebug() << "starting up!";
MainWindow w;
w.startApp(start);
w.show();
splash->finish(&w);
start->deleteLater();
splash->deleteLater();
return a.exec();
}
My only concern is that I use a Gif inside my widget using QMovie and updating it has to be done manually apparently.

If I understand your problem correctly (showing a dialog until your main window is created), you should have a look at the QSplashScreen class : http://doc.qt.io/qt-5/qsplashscreen.html

Related

Not able to connect signals and slots

I wrote a basic C++ program for simulating the signal and slot process. I made a push button "button", a QVBoxLayout "layout". I added the button in the layout. Everything is fine till now. But when push button is made to connect by signal and slot, there's are two problem/errors.
"no instance of overloaded function "QObject::connect matches the argument list"."
'QObject::connect': none of the 3 overloads could convert all the argument types.
Question:
I am sure that there's something missing, which I am not able to decipher. Here, the push button "button" has to invoke the function "connectFunc". Instead it gives me above two errors. How to make the button invoke the function?
This is my code.
#include "signalsslots.h"
#include <QtWidgets/QApplication>
#include<qpushbutton.h>
#include<qboxlayout.h>
#include<iostream>
using std::cout;
using std::endl;
void connectFunc()
{
cout << endl << "connected " << endl;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton* button = new QPushButton("Press Here");
QAction* bAction = new QAction;
button->addAction(bAction);
QVBoxLayout* layout = new QVBoxLayout;
layout->addWidget(button);
//layout->SetFixedSize(200, 150);
QObject::connect(bAction, SIGNAL(QPushButton::clicked()), &a,(connectFunc()));
QWidget w;
w.setLayout(layout);
w.setWindowTitle("Signal and Slot Example !!!");
w.show();
return a.exec();
}
FYI, I am using VS 2019 for writing Qt widget applications.
The QObject::connect() function that you use, connects a signal (i.e. a method) of an object to a slot (i.e. a method) of another object.
What you are telling QT is to connect the clicked() method of your QAction object, to the connectFunc() of your QApplication object. Both methods do not exist on those objects!
What you probably want is to connect the clicked() method of your QButton button to the free function connectFunc(). Like this:
QObject::connect(button, &QPushButton::clicked, &connectFunc);
Note that this requires QT5. (See Is it possible to connect a signal to a static slot without a receiver instance?)

Is it possible to use QGraphicsLayout in an application with a QMainWindow?

What I was hoping to do was have a standard QMainWindow class with menus, toolbar, plus various widgets in a layout, one of which would be a graphics view showing a graphics widget that contained a graphics layout. But whenever I put the graphics view into a main window nothing gets displayed. If I create my graphics view with the graphics widget containing a layout inside the main() function, then everything is visible.
As a test I took the working code provided in the Qt Basic Graphics Layouts Example, created a QMainWindow class in main, and moved the QGraphicsScene, Window and QGraphicsView creation to the main window class.
I tested the main window class on its own, and widgets like a line edit show up fine. But the code below, taken from main in the example, no longer works when in the main window class.
QGraphicsScene scene;
Window *window = new Window;
scene.addItem(window);
QGraphicsView view(&scene);
view.resize(600, 600);
view.show();
I just get a blank area. If I don't add the Window widget, but instead, for example, draw an ellipse then that is visible. If I add a plain QGraphicsWidget with a background colour then that is also visible. It is just when things are inside a layout on a graphics widget that I get nothing. I've been searching for answers, digging into the documentation and even looking through the Qt source to see if I can figure out if what I am trying to do is even possible, but without any luck.
My main window:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QGraphicsScene scene;
Window *window = new Window;
window->resize(600, 600);
scene.addItem(window);
QGraphicsView view(&scene);
view.resize(600, 600);
view.show();
setCentralWidget(&view);
resize(600,600);
}
Code in main:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
return app.exec();
}
One problem is here:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
[...]
QGraphicsView view(&scene);
view.resize(600, 600);
view.show();
[...]
}
You've declared the view widget on the stack, which means it will be automatically destroyed as soon as your MainWindow constructor returns, and thus the user will never see it. What you should do instead is something like this:
QGraphicsView * view = new QGraphicsView(&scene, this);
view->resize(600, 600);
view->show();
You'll have a similar problem with your QGraphicsScene object:
QGraphicsScene scene;
... since it is also declared as a local variable inside the constructor-method, it will also be destroyed when the constructor-method returns, leaving you with no scene. I suggest making it a class-member variable instead; that way it will last as long as your MainWindow does.
(Note that declaring items on the stack worked in the example-program you copied from, only because they were declared in the directly in the main() method, and main() doesn't return until the program is ready to exit... thus the objects in the example program would not be destroyed until the program was exiting anyway)

QMainWindow doesn't .show() but .showFullScreen() works

I have a desktop application that I'm building which checks a QSetting value and if it isn't set shows one QMainWindow class but if it is, shows a different QMainWindow class. The two classes are literally identical at this point as it's early on and don't really contain anything.
In my main function this is what I've got:
int main (int argc, char *argv[]) {
...
if (userToken == "NO_USER") {
LoginWindow w;
w.show();
} else {
MainWindow w;
w.show();
}
return a.exec();
}
The only difference in this between the default project set up from when I created the project is the addition of the conditional window load. Both MainWindow and LoginWindow don't have anything loading other than the ui file associated with them, they're functionally the same.
The weirdness is if I do w.showFullScreen() for the LoginWindow it will show up and take up the whole screen, if I do w.show() nothing at all happens, no compiler warnings|errors, application runs fine, just no window displays.
If I remove the conditional statements and LoginWindow references, MainWindow shows up fine.
Any idea why a call to .showFullScreen() would work but a call to .show() on the same class wouldn't?
I am not sure if this solves you problem, but there definitely is a bug in your code. You are instanciating the window objects on the stack inside a a tight scope, and as you know those objects will be destructed as soon as they go out of that scope. What you are doing is letting them go out of scope before the application is ever started.
Please try this instead:
int main (int argc, char *argv[]) {
...
if (userToken == "NO_USER") {
LoginWindow w;
w.show();
return a.exec();
} else {
MainWindow w;
w.show();
return a.exec();
}
}

Qt : pass values from a window to another

I have a Qt App running two windows, a login window and a data window. I need to be able to pass a couple of values from the first to the second, but i can't figure out a way to do it, since - on my main.cpp file - i have :
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
LoginWindow loginWindow;
loginWindow.show();
return a.exec();
}
What i'd want would be :
LoginWindow loginWindow;
loginWindow.who();
// wait for user to input data in LoginWindow.......
// fetch datas from loginWindow
SecondWindow secondWindow;
secondWindow.show();
So, as soon as my LoginWindow is closed (after the login), the whole app is terminated. Plus, i can't extract datas drom LoginWindow to the main function, since i don't know when they'll be available.
How can i make this work ?
Thanks.
I would declare a local variable in Main() and pass it by-reference to the login window's constructor, i.e.:
string username;
LoginWindow loginwindow(username);
loginwindow.show();
Where the constructor is declared like this:
LoginWindow::LoginWindow(string& username);
Then LoginWindow can modify the string however it needs to, and when the call to show() returns, the user name will be stored in the local variable username. You can then pass that to the constructor of secondWindow in the same way.
That's a proper place for Qt's signals and slots. The simplest way to get going - just add one signal to LoginWindow class and one slot to DataWindow class:
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
LoginWindow loginWindow;
DataWindow dataWindow;
QObject::connect(&loginWindow, SIGNAL(loginAcquired(LoginData)),
&dataWindow, SLOT(getLoginData(LoginData)));
QObject::connect(&loginWindow, SIGNAL(loginAcquired(LoginData)),
&dataWindow, SLOT(show()));
loginWindow.show();
return a.exec();
}

Qt: How to open a new main window on push button click and delete original main window?

I have files main.cpp, MainWindow.h and MainWindow.cpp. I have a push button on this original main window. What I want is when I click on the button, it should take me to a new main window and delete the original main window.
Also I want to follow good programming practices. So I am wondering that should new source and header files like SecondWindow.cpp/.h be created or all this be done in MainWindow.cpp where I have definition of the SLOT on_button_clicked()?
You need to:
Instantiate the new window and show it.
Delete the current window once the control returns to the event loop.
void MainWindow::on_button_clicked() {
auto win = new MainWindow();
win->setAttribute( Qt::WA_DeleteOnClose );
win->show();
deleteLater();
}
Make sure that the initial instance of the window is created on the heap:
int main(int argc, char** argv) {
QApplication app(argc, argv);
auto win = new MainWindow;
win->setAttribute( Qt::WA_DeleteOnClose );
win->show();
return app.exec();
}
The answer given by Kuba Ober works.However, you can have only 2 main windows at all times no matter how many times you press the button. It seems to crash the program after the second time you run it.
I believe my solution would be better since you can open as many main windows.
At your MainWindow Header:
private:
Ui::MainWindow *ui;
MainWindow *nWin; //Add This bit of code here
As for your triggered event function:
void MainWindow::on_actionNew_triggered()
{
nWin = new MainWindow;
nWin->show();
}
That should do it.
Thanks.