Function after setupUi()
-
You can't because you're assuming you can know when the last paint event is going to be dispatched and which paint event is "last", which is equivalent to asking a psychic about the future. We are talking event-driven programming here, so just respond to the relevant events. What is it that you want to do in that function anyway?
-
@kshegunov said in Function after setupUi():
You can't because you're assuming you can know when the last paint event is going to be dispatched and which paint event is "last", which is equivalent to asking a psychic about the future. We are talking event-driven programming here, so just respond to the relevant events. What is it that you want to do in that function anyway?
In function will be connecting to server, getting data from server, parsing data, etc. So I would like to create Dialog with progressbar like loader, which shows you what is program currently doing.
It is simple loader window, lot of apps use this.
I am looking for Form_Load function like in C#
-
It doesnt work
I added into mainwindow.cpp:
void MainWindow::showEvent( QShowEvent* event ) { QMainWindow::showEvent( event ); //your code here QThread::sleep(10); ui->progressBar->setValue(80); }
and mainwindow.h:
public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void showEvent(QShowEvent* event);
Problem is that, mainwindow shows after 10 seconds.
-
@t0msk said in Function after setupUi():
I am looking for Form_Load function like in C#
I don't know C#, but from a quick search it appears you want to put that code in the constructor after the
setupUi
call. Nothing is shown until the events are processed, so I don't see why you want to know when the window's shown. Just create your dialog and callshow()
on it (don't callexec()
as it will block the event loop). Connect the signals and slots as appropriate for the case. The data fetching and/or processing you can offload to a worker thread (for example take a look at the concurrent framework).@mrjj said in Function after setupUi():
To be sure main window is fully shown and then app will popup a Dialog over it then you can use
True, however you are probably going to get multiple show events, so then that part of the code would be executed multiple times. Additionally, you may not have a correct geometry at the time as there's no specific documented order of events; it all will depend on the underlying window manager (although from my experience one gets the show event last at least for Win and X11).
-
@mrjj said in Function after setupUi():
Hi
Do not use QThread::sleep(10);
You Freeze whole appfor 10 secs... :)Is there something else that sleep? Is there for example wait? Because sleep can means that app will freeze, but thread is locked in your app, something like mutex if you want to free thread.
My goal is that app will show Dialog where is progress bar and after all data fetching/processing is shown mainwindow and dialog closed.
-
@t0msk said in Function after setupUi():
Is there something else that sleep?
The point is you should not sleep.
My goal is that app will show Dialog where is progress bar and after all data fetching/processing is shown mainwindow and dialog closed.
Fine, so why have a main window at all. Also this in no way contradicts what I wrote, just call
show()
on whatever widget you want to show and connect the signals and slots appropriately. -
ok, so I created quite hard function for CPU, without sleep:
void MainWindow::showEvent( QShowEvent* event ) { QMainWindow::showEvent( event ); //your code here ui->progressBar->setValue(20); int i; double result; QString string; for(i = 0;i < 5000000;i++) { result = ((((i * 1337) / 7) * 3) - 5) % 1937; string = QString::number(result); ui->label->setText(string); } ui->progressBar->setValue(80); }
It took some seconds, BUT window displayed after math, so I cannot see initial value of progress bar (20). Sorry but I am confused.
-
Here, however I provide no text here as instruction. You need to read what an event loop is, how it relates to the GUI, what blocking the event loop means and how one can process things without blocking the event loop (multiple topics all available in the documentation).
#include <QApplication> #include <QProgressDialog> #include <QTimer> int main(int argc, char ** argv) { QApplication application(argc, argv); QTimer timer; timer.setInterval(100); //< Simulates a long running operation in the background timer.start(); QProgressDialog dialog(QStringLiteral("Test dialog"), QStringLiteral("Cancel"), 0, 100); dialog.show(); int counter = 0; QObject::connect(&timer, &QTimer::timeout, &dialog, [&dialog, &timer, &counter] () -> void { counter++; if (counter >= dialog.maximum()) { timer.stop(); dialog.close(); return; } dialog.setValue(counter); }); QObject::connect(&dialog, &QProgressDialog::canceled, &timer, &QTimer::stop); QObject::connect(&dialog, &QProgressDialog::canceled, &application, &QApplication::quit); return QApplication::exec(); }
-
Hi,
I would suggest looking into QSplashScreen it might me the class for your problems.
If I understand it correctly, you want to paint the gui, and than initialize the rest of your program displayed by a progressbar.
Simplest way to do this would be to call
QTimer::singleShot(10,this,&YourClass::SetupWithProgressbar);
out of your constructor, right after
ui->setupUi(this);
but, if your SetupCode is in the same thread as your progressbar, the pbar will most likely not update itself correctly. You'll have to do that manualy.
I hope this helps.
-
@J.Hilk said in Function after setupUi():
If I understand it correctly, you want to paint the gui, and than initialize the rest of your program displayed by a progressbar.
Exactly!
So my code now looks like this:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "QTimer" #include "QThread" void MainWindow::SetupWithProgressbar() { ui->progressBar->setValue(20); int i; double result; QString string; for(i = 0;i < 5000000;i++) { result = ((((i * 1337) / 7) * 3) - 5) % 1937; string = QString::number(result); ui->label->setText(string); } ui->progressBar->setValue(80); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTimer::singleShot(10, this, MainWindow::SetupWithProgressbar()); } MainWindow::~MainWindow() { delete ui; }
But I am getting an error:
error: invalid use of void expression QTimer::singleShot(10, this, MainWindow::SetupWithProgressbar()); ^
I think it is correct.
@kshegunov said in Function after setupUi():
Here, however I provide no text here as instruction. You need to read what an event loop is, how it relates to the GUI, what blocking the event loop means and how one can process things without blocking the event loop (multiple topics all available in the documentation).
#include <QApplication> #include <QProgressDialog> #include <QTimer> int main(int argc, char ** argv) { QApplication application(argc, argv); QTimer timer; timer.setInterval(100); //< Simulates a long running operation in the background timer.start(); QProgressDialog dialog(QStringLiteral("Test dialog"), QStringLiteral("Cancel"), 0, 100); dialog.show(); int counter = 0; QObject::connect(&timer, &QTimer::timeout, &dialog, [&dialog, &timer, &counter] () -> void { counter++; if (counter >= dialog.maximum()) { timer.stop(); dialog.close(); return; } dialog.setValue(counter); }); QObject::connect(&dialog, &QProgressDialog::canceled, &timer, &QTimer::stop); QObject::connect(&dialog, &QProgressDialog::canceled, &application, &QApplication::quit); return QApplication::exec(); }
Isnt it quite complicated for such simple thing? :/
-
@t0msk said in Function after setupUi():
error: invalid use of void expression QTimer::singleShot(10, this, MainWindow::SetupWithProgressbar()); ^
You're using the wrong syntax,
Use ne new one
QTimer::singleShot(10, this, &MainWindow::SetupWithProgressbar);
or the old one
QTimer::singleShot(10, this, SLOT(SetupWithProgressbar()));
If you mix them, the compiler will complain :)
-
@J.Hilk said in Function after setupUi():
@t0msk said in Function after setupUi():
error: invalid use of void expression QTimer::singleShot(10, this, MainWindow::SetupWithProgressbar()); ^
You're using the wrong syntax,
Use ne new one
QTimer::singleShot(10, this, &MainWindow::SetupWithProgressbar);
or the old one
QTimer::singleShot(10, this, SLOT(SetupWithProgressbar()));
If you mix them, the compiler will complain :)
Ah yes there is newer syntax :D So app was compiled successfully, but window displayed without UI (app freezes until math was completed), so i didint see "changing" progress bar.
-
@t0msk
well as long as you keep block the app , it will freeze like thatWhen you do
for(i = 0;i < 5000000;i++) {You kill the event loop and hence nothing else work.
An ugly and not recommended way is to call
QCoreApplication::processEvents()
in such loops but its not good design and not needed if you stop blocking it with loops. -
@mrjj said in Function after setupUi():
@t0msk
well as long as you keep block the app , it will freeze like thatWhen you do
for(i = 0;i < 5000000;i++) {You kill the event loop and hence nothing else work.
An ugly and not recommended way is to call
QCoreApplication::processEvents()
in such loops but its not good design and not needed if you stop blocking it with loops.I know that I am blocking app, but I dont know how can I create some "logic" (because every logic will occupy CPU) and display it by a progressbar.
-
Ok. so u know that the LOOP is the reason it do not work and you see NO change in the progress bar ?
Anyway, what is wrong with @kshegunov code ?
its 100% non blocking. -
@mrjj said in Function after setupUi():
Ok. so u know that the LOOP is the reason it do not work and you see NO change in the progress bar ?
Anyway, what is wrong with @kshegunov code ?
its 100% non blocking.Because I dont understand it, why there is timer? why is he setting a value into dialog and what is it mean?, I am newbie in Qt, so I am looking for simpler solution.
I used this in C# and it worked out of box.