Qt normal status bar not showing after temporary status - qt

Normal status message -these are always shown by an application unless a temporary message is shown. This is what I know about normal status message. So using these code on my constructor
ui.statusbar->showMessage("Temp message", 3000); // ui is the Ui::AutoGenHeaderForForm
QLabel *label = new QLabel;
ui.statusBar->addWidget(label);
label->setText("hello world");
I get that, when I run my project I get the status Temp message for 3 sec. Then I don't get the hello world back. Should the hello world come automatically after 3 sec in the position of Temp message ?

Assuming the code you show is in the constructor of your main window, the problem might be due to events not being properly processed because the event loop is not yet started at the time of the main window creation.
Try to execute the showMessage in a "delayed initialization" slot, e.g.
QLabel *label = new QLabel;
ui.statusBar->addWidget(label);
label->setText("hello world");
QTimer::singleShot ( 0, this, SLOT(delayedInit() );
void MainWindow::delayedInit()
{
ui.statusbar->showMessage("Temp message", 3000); // ui is the Ui::AutoGenHeaderForForm
}

I think the documentation is pretty clear:
The widget is located to the far left of the first permanent widget
(see addPermanentWidget()) and may be obscured by temporary messages.

Related

Showing progress window while creating other window/widgets

I have a function that looks like the following
void MainWindow::CreateEnvironment()
{
MdiWindow* sub = createSubWindow();
MyQTWidget* widget = CreateWidget();
..
..
}
I want that during this function a progress bar will be shown at the beggining and will close at the end of this function.
However adding
void MainWindow::CreateEnvironment()
{
**progressBarDialog->show();**
MdiWindow* sub = createSubWindow();
MyQTWidget* widget = CreateWidget();
..
..
**progressBarDialog->hide();**
}
Does not work, maybe because the function needs to exit first or something.
What is the best way to do this?
I assume that you use QProgressDialog?
You need to first setup the dialog with the correct number of steps you expect, how long you want to wait before it actually shows and more importantly: you need to call setValue() to update the progress bar.
Here is an example of how I would solve that (as far as I understand it)
void MainWindow::CreateEnvironment()
{
auto bar = new QProgressBarDialog(this);
bar->setLabelText(tr("Creating Environment..."));
bar->setCancelButton(nullptr); // No cancel button
bar->setRange(0, 10); // Let's say you have 10 steps
bar->setMinimumDuration(100); // If it takes more than 0.1 sec -> show the dialog
bar->setValue(0);
MdiWindow* sub = createSubWindow();
bar->setValue(1);
MyQTWidget* widget = CreateWidget();
..
..
bar->setValue(10);
MyLastWidget* last = CreateLastWidget();
bar->deleteLater(); // Not needed anymore, let's get rid of it
}
And don't worry too much if the dialog never shows. Unless you're doing really heavy computation (such as allocating / initialising huge portion of memory), creating widgets is very fast and would finish before the 100ms times out.
EDIT: Another thing to be aware of: QProgressDialog is meant to work after the main event loop started. (That is after the call to app.exec() in your main())
If you plan to show call this function in the constructor of your MainWindow, the dialog might even never show up because the window itself is not fully created and operational.
If you intended to call this function later, when the main window is already displayed on screen and the user hit a New Document button of some sort: you can ignore this part of the answer.

How to properly connect a QProgressBar with a QFutureWatcher?

I want the progress of the function to be displayed on progressBar. Following the guides, I wrote the code below. But during the execution of the function, the program freezes, then progress bar's value becomes equal to one.
The program itself will not produce errors. The result of the function is correct.
I think my problem is that I don’t know how to connect the value of the progress of a function with the value of a progress bar.
(Form.h)
public:
MyObject object;
QFutureWatcher<QBitArray> FutureWatcher;
QFuture<QBitArray> future;
(Form.cpp) Form constructor body:
ui->setupUi(this);
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(100);
connect(&this->FutureWatcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
(Form.cpp) Function on_button_clicked():
void Form::on_button_clicked()
{
QString message = ui->textEdit->toPlainText();
future = QtConcurrent::run(&this->object, &MyObject::longFunction, message);
this->FutureWatcher.setFuture(future);
QBitArray bitresult = future.result();
}
The problem is that you're immediately calling future.result(). The problem with this is that result() will wait until the QFuture has finished.
The Qt documentation says (https://doc.qt.io/qt-5/qfuture.html#result):
If the result is not immediately available, this function will block and wait for the result to become available.
The solution is to connect a slot to QFutureWatcher::finished():
auto *watcher = new QFutureWatcher<QBitArray>(this);
connect(watcher, &QFutureWatcher::finished, this, [=]() {
auto result = watcher->result();
// do something with the result
// important: delete watcher again
watcher->deleteLater();
});
// now start the task
QString message = ui->textEdit->toPlainText();
watcher->setFuture(QtConcurrent::run(myObject, &MyObject::longFunction, message));

Xamarin Forms Prism DialogService takes some seconds to show up

My Dialog is a simple Frame with an Image, a label to display a question and two more labels (Yes / No) with TapCommand.
I've set up the container with the DialogPage.xaml and DialogPageViewModel and injected in the ViewModel I want to open the dialog.
Here is the code I'm using to call the Dialog:
public void ShowDialog()
{
_dialogService.ShowDialog("DiscardPopup", CloseDialogCallback);
}
void CloseDialogCallback(IDialogResult dialogResult)
{
var goBack = dialogResult.Parameters.GetValue<bool>("GoBack");
if (goBack)
NavigationService.GoBackAsync();
}
If the user taps over the "Yes label", I execute this command:
YesCommand = new DelegateCommand(() => YesTapped());
private void YesTapped()
{
IDialogParameters pa = new DialogParameters();
pa.Add("GoBack", true);
RequestClose(pa);
}
If the user taps over the "No label", I simply call:
NoCommand = new DelegateCommand(() => RequestClose(null));
The "problem" is when the ShowDialog is fired, the DiscardPopup is taking up to 3 seconds to show up.
Is there a way to make it faster?
The same happens with the TapCommands, 2 - 3 seconds when the RequestClose is invoked.
Without actual code telling you exactly what the issue is, is going to be best guess. Based on your feedback to my comments above I would suggest the following:
Try displaying the dialog on a test page that doesn't have a complex layout. My guess is that you won't see such a long load time. If that's the case this would point to your layout being overly complex and that the lag time is due to the device struggling to re-render the View
Try using Prism.Plugin.Popups. You'll need to initialize Rg.Plugins.Popup and register the DialogService. You can see docs on that at http://popups.prismplugins.com

How to transfer Control back to the previous form?

I am new to Qt.
I am doing a project using Qt Creator. In my project, I have one mainWindow. From the main window I start 4 screens (one after another, showing Initialization process). A new QDialog screen is opened, if there are any errors on any screen. My error screens have two Button (Retry, Continue). If i press Retry, i have to restart the initialization process over again.
eg;
void ErrorScreen1::on_Retry_pressed()
{
Screen1 *scrn = new Screen1(this);
scrn->show();
this->close();
}
In above example, it restarts the process.
Is there any way, I can start the initialization process from the point it was left?
Thanks in advance,
In common you should somehow keep the current state of your process and then you can restore it.
Have you considered making those four dialogs into a wizard with four steps? The next button could work for the continue, and you could have a retry button on each page that it makes sense, with just that page doing the retry logic necessary.
I resolved this issue by using QMessageBox as my error window.
It allowed me to start my process from the point i left.
void Screen1::ErrorMessage()
{
timer->stop();
QMessageBox *msgbox = new QMessageBox(this);
msgbox->setWindowTitle("ERROR MESSAGE");
msgbox->setText("Initialization Failed.");
msgbox->setStandardButtons(QMessageBox::Cancel | QMessageBox::Retry);
msgbox->setDefaultButton(QMessageBox::Retry);
int ret = msgbox->exec();
switch (ret)
{
case QMessageBox::Retry: timer->start(); break;
case QMessageBox::Cancel:
timer->disconnect();
ui->progressBar->setValue(0);
break;
default: break;
}
}

QDialog::accept quits Main Application

I have a ClientSocket Class which is a TcpSocket in a certain state of conversation I need to ask the user to enter a Communication password. So I've created a Dialog DG::ChallangeDialog . in DG::ChallangeDialogs ctor I've
ui->setupUi(this);
QPushButton* okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
if(okButton != 0x0){
okButton->setText("Challange");
}
QObject::connect(this, SIGNAL(accepted()), this, SLOT(acceptedSlot()));
acceptedSlot again emits a signal challanged(QString)
void ChallangeDialog::acceptedSlot(){
QString text = ui->passBox->text();
emit challanged(text);
}
in ClientSocket I do
case Hallo:{
if(m->message().startsWith("welcome")){
DG::ChallangeDialog* dlg = new DG::ChallangeDialog;
dlg->setModal(true);
connect(dlg, SIGNAL(challanged(QString)), this, SLOT(challanged(QString)));
dlg->exec();
/*
DG::MessagePacket* res = new DG::MessagePacket((int)Hallo);
res->setMessage("challange");
send(res);
state = Challange;
*/
}
}break;
In ClientSocket::challange slot I send a Message challange (text) over the socket and store the password.
and I expect the Dialog to hide there and the normal socket conversation to continue. and after the Dialog is accepted or rejected the main application quits (It quits it doesn't crash). Why ?
My Application has no Other Widgets. I just works like an QCoreApplication. But still I've used QApplication cause I've some GUI Needs.
Is this the only window that is shown at this time? If so, I would guess that your QApplication instance is set to quit when the last window is closed. It is true by default.
If this is the case, you should explicitly set this to false before showing any windows.

Resources