I've got some code in my CMyView class. There I open a dialog with DoModal():
AnotherDialog dlg;
dlg.DoModal();
Now I want to automatically run a function. The poblem is, whenever I call dlg.DoModal(), the compiler waits till I close the Dialog window again, to continue running my code into the CMyView class. The function can also automatically be called into my AnotherDialog class.
Can anyone tell me, how I can automatically run a function whenever I open another Dialog?
AnotherDialog has a constructor, AnotherDialog::AnotherDialog(). Any function called from there will be called every time a dialog is created without providing arguments. If you add constructor overloads, each constructor can have different behavior, and it's up to you to make your code not confusing. (I.e. just be consistent)
If AnotherDialog is not your class, you may want to derive from it instead: class MyOtherDialog : public AnotherDialog. You can now have a MyOtherDialog::MyOtherDialog constructor which is called after AnotherDialog::AnotherDialog().
You could also add code to DoModal(), again in the existing class or a derived class.
The code in your view class is waiting because you are using the DoModal () method. By definition, DoModal is synchronous so it will wait for the dialog to close before continuing. Without knowing too much about your design, I would guess that you should use a "modeless" dialog invocation instead.
Related
I am developing Qt application (Qt version 4.7.3) on SBC6000x board.
I have a MessageBox class derived from QDialog. I have made this class singleton.
Whenever a messagebox is to be show I am using .exec method to show it.
There are few places where I need to show messageboxes one after another.
So, to show new messagebox, I have to close previous one and show new one.
e.g. When Messagebox is open and at same time I receive an error from background I have to close the messagebox which is currently shown and show the one with error.
To closes previous dialog I have exposed CloseDlg method from messagebox class and trying to close it.
Inside this CloseDlg I am emitting finished signal.
void CMsgBox::CloseDlg()
{
if (NULL != CMsgBox::m_msgBox)
{
if(CMsgBox::m_msgBox->isVisible())
{
emit CMsgBox::m_msgBox->finished(0);
//QApplication::processEvents();
}
}
}
and calling it as
CMsgBox::CloseDlg();
My show method is :-
int CMsgBox::showMsgBox(Icon icon, const QString &textMsg, const QString &okBtnText)
{
if (CMsgBox::m_msgBox == NULL)
{
CMsgBox::m_msgBox = new CMsgBox();
}
CMsgBox::m_msgBox->setText(textMsg);
CMsgBox::m_msgBox->setIcon(icon);
CMsgBox::m_msgBox->setOkBtnText(okBtnText);
CMsgBox::m_msgBox->exec();
return CMsgBox::m_msgBox->m_btnPressed; //return, unblock the call
}
Again when I call showMsgBox,it is showing me following warning.
QDialog::exec: Recursive call detected
Problem is, it doesn’t return from previous exec call (unless we return, as commented above //).
I tried same with close(), accept(), reject() methods instead of finished() event but nothing worked.
What is the way to return from previous exe call and achieve above scenario? Any help is welcome.
What you have here looks like a race condition. A modal QDialog runs its own event loop, so your application behaves like a multithreaded application and you need to take care of concurrency and race conditions.
When you receive a second in your main event loop, you call CMsgBox::CloseDlg() and CMsgBox::showMsgBox() in quick succession. However, CloseDlg() tells the dialog's event loop to return, but CloseDlg() actually returns before the dialog's event loop is done cleaning up, and showMsgBox() attempts to call exec() on a dialog which hasn't finished exiting yet.
What you need to do is, when you call CMsgBox::CloseDlg(), connect to the finished(int) signal, and only when you receive the finished(int) can you safely exec() the dialog again.
NOTE: When connecting to the finished(int) signal, make sure to use a Qt::QueuedConnection instead of a Qt::DirectConnection which is the default.
So, you need modeless dialog box. As explained in their documentation :
Modeless dialogs are displayed using show(), which returns control to the caller immediately.
Therefore, instead of showing the box with exec(), show it with show().
Alternative to show() method suggested in another answer is, use QDialog::open(). It will return, but will still give you modal dialog, so the rest of the GUI will be disabled until you close it.
I'm writing an MFC CEdit derived control, and I need to add initialization code once the control's m_hwnd is filled.
Which function can I override or which message can I handle to achieve this?
I tried with OnCreate, but It seems to work only for dialogs
EDIT:
The thing I'm initializing is the edit's cue banner
Thanks
Following Mark Ransom's hint, I finally found a better function to implement my intitialization. While overloading CWnd::SubclassWindow is a good idea, this function is not virtual and it would require a call from the subclass pointer. Calling SubclassWindow from a CWnd* would not work.
I found the function CWnd::PreSubclassWindow. It's virtual and is called just before SubclassWindow. Since m_hwnd is valid there, it is a good place to write the code I need.
In addition, the function is virtual and is called automatically by the framework so I don't need to worry about having the good pointer type
OnCreate doesn't work if the control is on a dialog, because the control is created before it can be subclassed to your window class - that happens in the dialog's DoDataExchange.
You can override CWnd::SubclassWindow and call the base method before your own code.
Depending what exactly you are initializing, you can override OnPaint(), or you can add your initialization code into the OnInitDialog() in the Dialog class that the control is contained in.
How do i hide a toplevel window without closing it?
NdmWindow is a class inherited from Gtk::Window.
I have added the instance of NdmWindow to Gtk::Application.
Now, how do i hide it instead of closing it?
Thanks in advance..
According to this, the behavior is that when a window is hidden, it is removed from Gtk::Application, and so if it is the last window, the app quits.
If you want your application to keep running when no windows are showing, the solution is to call hold() on your Gtk::Application object to increase the reference count of the application. Presumably you do this before setting up any windows, and call the corresponding release() as part of your quitting logic.
window->hide();
Don't forget to look at classes that Gtk::Window inherits from.
EDIT
I don't know, but my suggestion is to try hold(), and then release() after you show the next window.
Here's a solution that works and doesn't segfault.
Save a reference to Gtk::Application, say send it as a param to your main Window class and call this var app, you'll need it later, it's needed because in some cases get_application() will return null.
In the delete event handler of your window call
app->hold();
hide();
return true;
Don't call app->release() when you want to make your window show up again since it will make your application exit completely. Just call set_visible() on your window object and it will show up.
I have a custom class inheriting from QDialog. I'm creating this dialog with function foo, and foo would like to continue doing its thing only when a certain button in the dialog is pressed. I was thinking of using signals and slots, but then how could I get foo to respond to a signal from another thread?
EDIT: basically I want to know how to reimplement the functionality of QInputDialog::getText() using my own dialog.
Your foo() function could call wait() on a [QWaitCondition][1] object, then your button could call wakeOne() on the same object to cause the wait() to return.
That said, there is really no necessity for using multithreading to reimplement QInputDialog::getText(). You should be able to reimplement that functionality inside a single thread without any problems, and doing it that way will be much simpler and more reliable.
(Note: assuming you want your version of getText() to block and not return until after a button is pressed, you'll need to call QDialog::exec(). I don't recommend that style of programming though, as it's error-prone... for example, what happens if the user closes your QInputDialog's parent window while the QInputDialog is still open? That deletes the QInputDialog object whose getText() method the program is still blocked inside, likely causing a crash because the QInputDialog's "this" pointer is now a dangling pointer. It's much cleaner and safer to make everything event-based instead (i.e. signals and slots only), and not attempt to block or recurse Qt's event loop in your own code)
http://doc.qt.io/qt-4.8/qdialog.html#modal-dialogs
Modal dialogs will block the user from interacting with other windows, which it sounds like you will need. Also, I think you want to call exec() instead of show(). Show() returns execution to the caller immediately, where as exec() blocks.
I've used MFC dialogs before where you do:
EnterNameDlg dlg;
dlg.DoModal();
string str = dlg.GetName();
However a dialog I have now actually looks at a list-box control in such a method and it's not working. Although the class instance clearly exists after DoModal(), does the actual dialog get destroyed? I noticed calling DoModal() a 2nd time leads to OnInitDialog() also being called again which seems to support this theory, the dialog is recreated from the template rather than simply made visible the 2nd time.
Yes, DoModal creates a dialog on each call and destroys the window before returning.
Only the data members will still be valid. Of course, you can add more data members in your EnterNameDlg class if you want to collect data during dialog's lifetime.
As soon as the dlg gets out of scope, everything will be deallocated.
After DoModal class instance still exists, but window and all its controls are destroyed. You can call only functions that don't work with dialog controls after DoModal. Inside of the dialog class, keep required values in class members like CString, when OK button is pressed. These members can be read after dialog is closed.
The entirety of MFC is built around an awkward pairing - the Windows window with its associated handle, and the MFC class object. The MFC classes are designed to outlast the window in most cases.