I'm doing a QWizard with QT 4.8.5 and in some pages I have to close some other applications and exit my program. This works fine but now I want to show a pop up message that tells the user that the programs are restarting (There are others a part of mine and mine is the last one to be closed always). The code I use to show the pop up is the next one and I place it in the validatepage of a QWizardpage:
QMessageBox *msgBox1 = new QMessageBox;
msgBox1->setWindowTitle("Title...");
msgBox1->setIcon(QMessageBox::Information);
msgBox1->setText(" blablablalbal bla bla bla.");
msgBox1->setWindowModality(Qt::NonModal);
msgBox1->show();
QCoreApplication::processEvents(); // without this line, the show does nothing and I can't see my pop up window
So the thing is: With that code, When I am in that wizardpage and click to finish, it launches the QMessageBox while (behind) the program is restarting the other applications and then closes itself (with a QApplication::quit(); ) which is exactly what I want... BUT no message is shown in the pop up... I can't see the icon, the title or the text... :S I don't know why :(
Whereas when use ->exec(); instead of show, the icon, title and text are shown BUT when the pop up appears, nothing is done behind until the user closes that pop up... :S
I understand that .exec() freezes all until user closes the pop up while show doesn't...
So... how can I see the text with the show() behaviour?? I don't want the user to interact with that pop up, I just need the pop up to show up while closing all until my program closes too...
Thank you so much!
Relevant: http://comments.gmane.org/gmane.comp.lib.qt.general/30706
In summary, QDialog::exec() creates a modal dialog (regardless of your Qt::NonModal setting) with its own event loop, and ::show() does not.
So in your case, ::exec() will fully render the dialog but it's blocking the rest of your background processing. ::show() won't block, but since it's sharing the event loop with your other code it isn't getting around to emptying the event queue (which has all of the show/layout/render events from your dialog) because of your background code.
I would try the following:
use ::show() not ::exec()
force your dialog to the front using QDialog::raise() and Dialog::activateWindow()
(the important part) either
call QApplication::processEvents() within your background processing tasks (e.g., within long-running loops).
spawn your background processing into a thread (this may or may not be easy depending on how your code is structured) to allow the main event loop to process your dialog events.
Related
I have dialog box and in it, it has OK and Cancel buttons then it also has a ListBox to display text in two columns. I would like to continue adding text into the ListBox after the dialog box is shown. How can I do that? Because after I call DoModal() to show the dialog box, the code does not continue to execute. Or should I create two threads (one is display dialog box while another thread continues adding text to dialog box)?
Make your dialog 'pull' the data it needs, maybe polling the data source with window messages every second, or every 100ms or so. Or, if you go the 'two threads' route (the better but more complicated option), have your data source post a window message to your dialog when there is new data, and then have the dialog fetch the data it needs. The reason for this is that it's much easier to use the existing CDialog infrastructure to get a window that behaves like an actual dialog, compared to building a modal window that acts like a dialog but isn't really.
If you do go the two threads route, your division of labor should be: one thread that does all the UI work (including showing the dialog), and one that 'generates' data and lets the UI know when there is new data. So the worker thread should not do anything related to the UI, nor call any methods on the dialog directly - you can't access windows from several threads. The only cross-thread window communication should happen through window message (i.e., use ::SendMessage()). So certainly don't do something like myDialog->m_theList.AddString("blah") from another thread, or something like it.
Showing a dialog box modally halts further execution until you close the box. Instead of showing it modal, show it normal but make it always on top so you can continue executing the code after the call to DoModal(). Alternatively, populate the box with all the info it will need before you call DoModal().
If you decide to take the "two threads" approach you will discover that the controls on MFC dialogs should not be updated or accessed from a thread other than the one that created the dialog. Even if you have pointers to these controls available in another thread it is not thread-safe to access them. This rule applies whether or not the dialog is modal.
Instead, your second thread would need to PostMessage or SendMessage to the dialog window, so the updates occur on the thread that created the dialog (most likely the main UI thread of the application).
I need a wait cursor to be loaded when the second page OnWizardNext of a property sheet is clicked .This is how I had done.Actually I designed a property sheet and now when I Click on the Next button I had activated the hourglass ,till this point everything works fine ,here arises the actual problem i.e,during that wait cursor period if I click again on Next button the dialog is getting dismissed .So,my intention is even if I click Next during the wait cursor it should not react to the click event.
LResult OnWizardNext()
{
CWaitCursor wait_cursor();
Sleep(10000);
return CPropertyPage::OnWizardNext()
}
if I remove Sleep then no wait cursor is getting loaded.What I need is even though if click on any button anything the event for that button should not get triggered until unless i am out of sleep time.
Can anyone please let me know how to achieve this.
I think you have a problem with the design of your wizard. You should not be using "Sleep" as it will suspend the thread. Moreover, the wait cursor is nothing more than a UI mechanism to indicate to the user that the code is still active. You seem to want to use that as a determinant for when your code can continue. Take a look at using OnSetCursor to provide visual feedback. Depending on what it is you're waiting on, you may want to look at using a timer, or, perhaps a series of "flags" to indicate a "continue" condition.
I have a desktop windows application programmed in C++ with Qt. The application has several top - level windows which occasionally need to be closed and recreated programmatically. Also, when the user of the program clicks on the close button (the one next to the minimize and maximize buttons) the whole program is supposed to exit.
The problem I have is that in both cases the top level windows receive a closeEvent() call with a QCloseEvent object. I'd like to quit the program when I see that happen (because the user might have clicked the close button), but it's also possible that the window is closing because I'm deleting it programmatically to recreate it.
Is there a way of distinguishing between these two cases in QMainWindow::closeEvent()?
Is there a way of distinguishing between these two cases in QMainWindow::closeEvent()?
Yes: the close event triggered by the user clicking on the window's close button will be a spontaneous event, the one triggered by you calling window->close() will not. See the documentation of QEvent::spontaneous() for more information.
When you need to close your window programmatically, use deleteLater() instead of close. The window will be closed and deleted. To reopen the window you will need to create another window object.
You can also use hide() method. The window will be hidden but not destroyed. It can be shown again using show().
In both described cases the close event does not happen and closeEvent() isn't called. So when closeEvent is called, you know that the user has pressed the close button.
Good day!
I have an MFC dialog with progress.
Dialog automatically closes after reaching 100% using PostMessageW(WM_CLOSE).
The problem is, when, during progress, I'm moving dialog over the screen, dialog is not closing and WM_CLOSE message is ignored. Any suggestions? Thanks.
For a modal dialog you shouldn't really need to use a WM_CLOSE message.
Normally you'd use the OK or Cancel button events to close it, call the EndDialog method from functional code or just return when your processing is complete (assuming that its the process run as soon as the dialog is initialised). You can set your return value at the same time e.g. EndDialog(2);.
Either way the dialog will close once th current message handler returns, so there could well be a delay, in closure but it shouldn't be much.
Is the activity behind progress bar done in a separate thread? It look like to be the case otherwise when you drag the dialog the progress bar would have froze until you release the dialog than it would have resumed. This means you might have to look into inter thread communication, how the message is being posted to the dialog HWND.
It might have to do with the dialog being in freeze (no activity) state while you are dragging it which seems to be normal windows behavior. If that is the case you could use signals/CEvent to tell the dialog to close down.
My FoxPro program has a quit button and the usual min/max/X buttons in the top right, and when using either the program disappears and seems to have closed properly. However, when I check my Task Manager, I find that it is still running.
This is my main.prg file:
ON SHUTDOWN CLEAR EVENTS
with _screen
.visible = .f.
endwith
DO FORM locations\form1
READ EVENTS
ON SHUTDOWN
and this is the code for my exit button 'click' event:
unlock all
close database all
clear events
RELEASE ALL
quit
My program has only the one form and it's set as top-level... any suggestions as to how I can fix this?
Thanks for your time and help :)
If you are running VFP originating from the IDE (Development environment), and you do _Screen.Visible = .F., you are HIDING the main VFP screen, and the system may be returning directly to that, and since you can't see it, you cant formally quit.
In your MAIN.PRG, put the following down at the bottom as a separate "function" that will be visible within the call stack.
function CloseMyApp
*/ For now, just to "ignore" any errors of any dangling objects trying to get released
*/ and otherwise might be HIDING an error upon shutdown.
on error *
*/ NOW, clear the event handler and close everything else down
clear events
close database all
close tables
on shutdown
quit
endfunc
Then, in your start, change your ON SHUTDOWN to call this "function"... Right now, you are only issuing a single command of clear events. This way, you can wrap up a bunch of "cleanup" operations before closing, and not just clearing the read events.
ON SHUTDOWN Do CloseMyApp in Main.PRG
If you click the EXIT button on the form (your button) does the form close and the application close correctly ?
If it does, ASSUMING the button is called 'cmdExit' then add this line to the 'UNLOAD' event of the form
THISFORM.cmdExit.click()