MainWindows::MainWindow(QWidget *parent) :
QMainWindow(parent) , ui(new Ui::MainWindow) {
ui->setupUi(this);
some initialization code here
}
I want to terminate the whole application if the initialization failed, how could I do this?
Thanks.
qApp->exit() and this->close() both won't work when called within MainWindow's constructor.
The normal Qt int main() function looks like this:
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return application.exec();
}
...and qApp->exit() only works from within the qApp->exec()/application.exec() main loop, which, as you can see in int main(), you aren't yet within. It therefore has no effect.
And with this->close(), MainWindow() hasn't finished been created yet, and hasn't been shown yet, so it's not open - if it's not open, it can't be closed. =)
Using delayed initialization
I think the easiest way to solve this is to delay your initialization until after the constructor finishes:
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
MainWindow mainWindow;
if(mainWindow.Initialize() == false)
return 0;
mainWindow.show();
return application.exec();
}
Normally I prefer/recommend initializing in the constructor of classes, but here an exception needs to be made to work around this unusual circumstance.
Using a 'failed state' flag
Other ways of doing the same thing would be to continue to initialize in the constructor, but use a flag to mark that the MainWindow has "failed to initialize":
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
MainWindow mainWindow; //Initialize in constructor, like normal.
if(mainWindow.Failed()) //Check results.
{
return 0;
}
mainWindow.show();
return application.exec();
}
Using exceptions
Exceptions are also another way to handle this situation - but make sure you catch it, so no error messages get displayed by the OS (I forget if Windows detects). In your initialization, you report the error yourself, so you can report it with details.
int main(int argc, char *argv[])
{
QApplication application(argc, argv);
try
{
MainWindow mainWindow; //Initialize in constructor, like normal.
mainWindow.show();
return application.exec();
}
catch(...)
{
return 0;
}
}
How about exit() ?
MainWindows::MainWindow(QWidget *parent) :
QMainWindow(parent) , ui(new Ui::MainWindow) {
ui->setupUi(this);
//some initialization code here
if (something_failed)
{
exit(1); // terminate process
}
}
This works for me:
QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);
you can use the assert method to terminate the program which will automatically chescks the condition, if the condition becomes false it terminate the program giving the line at which it terminated. The syntax is as follows:
Q_ASSERT(condition);
I want to terminate the whole application if the initialization failed, how could I do this?
Throw exception from the constructor. By default unhandled exception will terminate the whole application. You could also call QCoreApplication::quit - however it'll be better to still throw an exception, catch it elsewhere, and use QCoreAPplication::quit if things went really wrong.
Simply calling exit may result in data loss if you're, say, writing files.
Related
I have a simple Qt application in Visual Studio:
int main(int argc, char* argv[]){
QApplication app(argc, argv);
Myclass* c = new MyClass;
c->show();
int ret = app.exec();
return ret;
}
but my application does not return when I close the windows (in debug mode, app.exec() does not return).
The process and sub process Qt Qtwebengineprocessd remains in execution.
How can I control/debug in Visual Studio why/where my application is blocked?
According to the Qt documentation for exec you have to call QApplication::exit(code) or QApplication::quit() for exec to return. You should probably call one of these functions when you detect a QCloseEvent in your MyClass widget.
If the class that instantiate MarbleWidget class have a QMainWindow(parent) can be added void MyClass::closeEvent(QCloseEvent *e){delete c;}
If there are no QMainWindows or QDialBox add in the main:
app.closeAllWindows()
and in the destructor:
QApplication::quit();
i'm trying to group multi (Push Buttons) into an exclusive group, but i don't know how,
when i tried this example [Link] on its own it worked,
but when i try it on my project it failed
NOTE: all my UI elements are graphically implemented not code implemented,
also i'm using (Qt Creator) only
i tried the following
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Test01 window;
QButtonGroup apple (&window);
apple.addButton(&PB01);
apple.addButton(&PB02);
apple.addButton(&PB03);
apple.setExclusive(true);
window.show();
return app.exec();
}
but it didn't work, not the following either
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Test01 window;
QButtonGroup apple (&window);
apple.addButton(&ui->PB01);
apple.addButton(&ui->PB02);
apple.addButton(&ui->PB03);
apple.setExclusive(true);
window.show();
return app.exec();
}
i tried on the cpp file, like the following
Test01::Test01(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Test01)
{
ui->setupUi(this);
QButtonGroup apple (&Test01);
apple.addButton(&ui->PB01);
apple.addButton(&ui->PB02);
apple.addButton(&ui->PB03);
apple.setExclusive(true);
}
but didn't work either
can you please provide the solution
also what's the deference between write this code in (main.cpp) & in (test01.cpp) file
to answer your question correctly, it would be nice to provide the ui-Code of your form.
Howevery, one reason could be, that you missed the checkable property of QPushButton.
To work as a button group every QPushButton must be marked as checkable either by code:
PB01->setCheckable(true);
or by Qt Designer.
Greetings, Thomas
I want to create a file that contains and manages the entire UI outside of the main.cpp and its main function.
To start I used the code from this answer, which worked fine
from inside the main method.
To prevent information loss I show the code below as well:
#include ...
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsPixmapItem item(QPixmap("c:\\test.png"));
scene.addItem(&item);
view.show();
return a.exec();
}
I tried to outsource this code into an own
class, but after executing the shown code the just created window
disappeared again within a few milliseconds without a warning or an error.
To check if I made a mistake within my own class I tried to use this code
from an own function within my main.cpp
void initUI(QApplication * application){
QGraphicsScene scene;
QGraphicsView view(&scene);
QGraphicsPixmapItem item(QPixmap(application->applicationDirPath() + "\\graphics\\Theme1\\background.png"));
scene.addItem(&item);
view.show();
}
But the same problem ocurs here. Why does the shown code needs to be executed within the main method, and how could you outsource it?
In case this information helps: I'm running on windows with Qt Creator 3.6.1
based on Qt 5.6.0 (MSVC 2013, 32 bit)
Edit:
Here is my main method
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
initUI(&a);
return a.exec();
}
Edit 2:
The error does not occur when I add an
application->exec();
Can somebody explain why this happens? What is the difference between
the call of application->exec() in the initUI-method and the a.exec() call
within the main method?
The destructors of scene and view are called once you exit initUI, as it is put on the stack. You need to put it on the heap in order to survive after exiting the init function. Of course you should take care of dangling pointers.
I have just started developing using QtGUI and I have checked out some tutorials and documentation, and by what I've read this should work.
#define CONNECT QObject::connect
void test();
QPushButton *lpTestBtn;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtProject w;
w.show();
lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
CONNECT(lpTestBtn, SIGNAL(clicked()),qApp,SLOT(test()));
return a.exec();
}
void test()
{
lpTestBtn->setText("Hi");
}
But test() never gets called. Also, lpTestBtn is not null and is found correctly.
I have tried the following changes
CONNECT(lpTestBtn, SIGNAL(clicked()),qApp->activeWindow(),SLOT(test()));
CONNECT(lpTestBtn, SIGNAL(clicked()),w.window(),SLOT(test()));
I know I can just do QtProject::on_TestBtn_clicked(); but I'd like to get it working using CONNECT,SIGNAL and SLOT.
The test function in your code is not a slot, nor does it belong to the Q(Core)Application class as you seem to have used it.
The best would be is to move that one line in the test function to the connection with the lambda syntax. This will require C++11 support, but that is in quite common use these days.
You would use the new shiny signal-slot syntax. This would spare you some headache for runtime issues in the future because they would appear at compilation-time.
Therefore, you would write something like this:
main.cpp
#include <QMainWindow>
#include <QApplication>
#include <QPushButton>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
// Replace it with "QtProject".
QMainWindow w;
w.show();
QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
QObject::connect(lpTestBtn, &QPushButton::clicked, [=]() {
lpTestBtn->setText("Hi");
});
return a.exec();
}
main.pro
TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Please also note that it is bad idea to create a global pointer for a QPushButton object. It not only leaks the memory, but you could have other issues, too.
1) QApplication doesn't have a test() slot in it. You need to make your own class, inheriting QApplication, and give that class a test() slot. What you've done is create a regular function, which won't help.
2) You didn't check the return value of connect, which means you didn't see that it was giving you an error, which would probably have given you some clues.
You can connect signals to the slots which are in classes derived from QObject so meta compiler can deduce slot calls. But your test() is global function. You have to put your slot function inside a class that derives from QObject and supports Q_OBJECT macro or define a lambda function ( with C++11 support) as Laszlo Papp showed.
Example:
// testwrapper.h
class TestWrapper : public QObject
{
Q_OBJECT
//...
public slots:
void test();
};
// main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtProject w;
w.show();
QPushButton * lpTestBtn = w.window()->findChild<QPushButton*>("TestBtn");
TestWrapper tw;
CONNECT( lpTestBtn, SIGNAL( clicked()),tw,SLOT( test()));
return a.exec();
}
I managed to write a "Gui Unit Test" using this tutorial. However, when I compile my code I get this:
PASS : testUnits::initTestCase()
PASS : testUnits::toUpper()
QFATAL : testUnits::testGui() QWidget: Must construct a QApplication before a QPaintDevice
FAIL! : testUnits::testGui() Received a fatal error.
Unknown file(0) : failure location
Totals: 2 passed, 1 failed, 0 skipped
********* Finished testing of testUnits *********
why is it giving me: Must construct a QApplication before a QPaintDevice ?
it works now, here is my Gui unit test function definition:
void testUnits::testGui(){
QLineEdit lineEdit;
QTest::keyClicks(&lineEdit,"hellow world");
QCOMPARE(lineEdit.text(), QString("hello world"));
}
and here is how my main() looked like before fixing the problem :
int main(int argc, char *argv[])
{
testUnits testString;
QTest::qExec(&testString, argc, argv);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
So, when I compile the code, it execute the unit test before constructing the QApplication.
Therefore I put my QTest::qExec() after QApplication and now it works and the main() looks like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
testUnits testString;
QTest::qExec(&testString, argc, argv);
return a.exec();
}
It's better to not define your own main manually. All of the test logic, including the required preconditions, shall be made within the test object (the QObject subclass with the test* slots) itself. See the QTestLib manual for details.
If you do this, then simply using the QTEST_MAIN will do the right thing and save you some time.