How to set input focus to a shown dialog in Qt? - c++

In a button click slot, I create and exec() a dialog with a NULL parent. Inside the dialog's constructor, I have:
this->activateWindow();
this->raise();
this->setFocus();
The dialog is application modal and has strong focus. However, it does NOT respond to keyboard events until I click on it. How do I make the dialog get focus without having to click it?

The problem was that I was setting the Qt:Tool window flag. Using Qt::Popup or Qt::Window instead will cause input focus is automatically set when the dialog is shown.
I used Qt::Window myself. Some of the other flags will probably work as well, but the main thing is that a QDialog with the Qt::Tool flag will not automatically set input focus when the dialog is shown.

Install the Event filter for the dialog.
classObject->installEventFilter(this);
void className::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Space)
{
focusNextChild();
}
else
{
QLineEdit::keyPressEvent(event);
}
}
for more info refer here.
http://doc.trolltech.com/4.6/eventsandfilters.html

In my case even settings Qt::Window didn't do the trick. I had to
QMetaObject::invokeMethod(widgetToFocus, "setFocus", Qt::QueuedConnection);
before show() or exec().

Related

In MFC Close only the Child Dialog, not the Parent

I'm a newcomer to MFC world. I need to have some dialog based operaion for an old application. There I'm having a trouble for an appraently obvious thing and that is I can't seem to find a way to close the child dialog (Modal) that I'm invoking from my parent (also a Modal). In all the ways I tried always both child and parent is getting closed at once.
Here is what I tried:
I've created a default MFC application in VS 2012 Professional
ParentDlg.cpp
void ParentDlg::OnBnClickedOk()
{
ChildDlg childDlg;
dialogOutput.DoModal();
CDialogEx::OnOK();
}
In my Child.cpp for a Close button (ID: IDCLOSE)
ChildDlg.cpp
void ChildDlg::OnBnClickedClose()
{
// TODO: Add your control notification handler code here
EndDialog(IDCLOSE);
}
But this is closing both the parent and child, but I need only the child dialog to be closed (Parent Dialog should remain open) as I'm clicking the 'Close' buton on the child dialog.
In short, I like to have the same behaviour of the default IDOK button of 'IDD_ABOUTBOX' dialog, which is also a Modal dialog and closes only the About Box when I click on the 'OK' button in it.
You should only place IDOK in the ID property of your close button. And only the child dialog will close. You should no longer create an event handler, and if you did, delete the event handler.

QT dialog close and delete

I have a MainWindow and Type class.
A button in the MainWindow sends a signal to a slot with this code:
dialog = new QDialog(this);
Ui_type typeui;
typeui.setupUi(dialog);
dialog->show();
The dialog then shows. When a button is clicked on the dialog, I want to close the dialog and delete it.
I don't understand how to refer to the dialog from the dialog itself.
Any help would be appreciated. Thanks.
You can set Qt::WA_DeleteOnClose attribute on your dialog. This will ensure that the dialog gets deleted whenever it is closed.
Then call close() method in the dialog when your button is clicked.
dialog = new QDialog(this);
Ui_type typeui;
typeui.setupUi(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
Refer to the documentation for details :
QWidget::setAttribute ( Qt::WidgetAttribute attribute, bool on = true )
Qt::WidgetAttribute
First the close button is at the dialog window right, then most easy way to do it, is create a button, and connect the close() function to response the click() signal.
like:
Dialog::Dialog(){
// other code
QPushButton *closeButton = new QPushButton(tr("Close"));
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
// other code
}
Under the Qt/examples/dialog projects are good reference for your question. check it out.
The simple way to get input from a modal dialog is QDialog::exec(). This may handle everything you need.

QT Modal Window and Disabling parents toolbar

I am developing a project using Qt4 and I have run into a slight issue.
I am creating a modal window from the main window. I want this to disable the toolbar at the top.
I have a menu item that spawns the modal from the menu. What I want is that when the modal is spawned that menus is disabled. I have tried using the setEnabled(false) function but that doesn't reset it.
Here is the code:
void Main_Screen::Create_ViPro()
{
std::auto_ptr<ViPro_Dialog> modal(new ViPro_Dialog(this));
modal->show();
modal->exec();
}
So It is just a simple class that is triggered when a menu item is selected. I feel that the problem stems from the fact that i'm setting the parent to the main screen, however I don't know how to create a modal without a parent(it doesn't make sense to do that). Is there a way to disable the parents toolbar from the child? The only thing I have seen so far is _fileMenu->setEnabled(false);
That works as long as I don't create the modal, but as soon as that is spawned, the menu works again. I'm totally lost.
Thanks in advance
Edit as Patrice
Here is the constructor
Main_Screen::Main_Screen(QWidget* parent /*= NULL*/)
: QMainWindow(parent),
_newProj(new QAction(tr("New &ViPro"), this)),
_fileMenu(menuBar()->addMenu(tr("&File")))
{
//create slot for creating a new project
connect(_newProj.get(), SIGNAL(triggered()), this, SLOT(Create_ViPro()));
_fileMenu->addAction(_newProj.get());
//if i do this then setEnabled(false) works perfectly and i can't access the menu
Create_ViPro()
}
So the function is signaled by triggering the newproject action. If i call the function directly from within the constructor it disables it as you stated patrice, however, if I have the function called via the trigger, it doesn't disable it. Am I handling the signal / slot mechanism wrong? Thanks again.
Another example, if I make the function create_vipro() as below
void Main_Screen::Create_ViPro()
{
_fileMenu->setEnabled(false);
}
The file menu isn't disabled when I trigger the event, so it must have nothing to do with the modal itself, but instead how signals are handled.
Since child is a modal dialog main screen can't react to event. But you can disable the toolbar (or menubar) before creating the modal dialog and enable it as soon as you leave the exec function:
void Main_Screen::Create_ViPro()
{
_fileMenu->setEnabled(false);
std::auto_ptr<ViPro_Dialog> modal(new ViPro_Dialog(this));
modal->show();
modal->exec(); // Will stay here until you close the modal dialog
_fileMenu->setEnabled(true);
}
if ViPro_Dialog is really a modal dialog it will works.
Another thing, since ViPro_Dialog is modal you can declare it locally without using auto_ptr:
void Main_Screen::Create_ViPro()
{
_fileMenu->setEnabled(false);
ViPro_Dialog modal(this);
modal.show();
modal.exec(); // Will stay here until you close the modal dialog
_fileMenu->setEnabled(true);
}
EDIT:
I guess (I can't test at work) that you can't enable/disable menu when it is executing a QAction. Signal is calling slots sequentially so QAction is busy when you try to disable the menu.
Try this:
In Main Screen, create a slot with one boolean parameter that enable/disable menubar. Just call the setEnabled function
In ViPro_Dialog, emit a signal with a boolean parameter (false at startup, true at validation)
In Create_ViPro, once dialog created, connect the new signal with the slot, exec dialog and don't forget to disconnect slot from signal:
void Main_Screen::Create_ViPro()
{
ViPro_Dialog modal(this);
// Connect signal/slot
modal.show();
modal.exec(); // Will stay here until you close the modal dialog
// Disconnect signal/slot
}
This can achieve what you want
EDIT2
You are doing a mistake when using modal dialog. There's a conflict between show() and exec(). When you are displaying modal dialog you don't need to disable other windows: it's automatically done by modal status of the dialog. There are many modal depth: http://qt-project.org/doc/qt-4.8/qt.html#WindowModality-enum. So your code should be:
void Main_Screen::Create_ViPro()
{
ViPro_Dialog modal(this);
// modal.setWindowModality(Qt::WindowModal); // Uncomment this line if you want to only disable parent
modal.exec();
}
Read this for more detail: http://qt-project.org/doc/qt-4.8/QDialog.html#details.
Using exec() doesn't just create a modal dialog, it also suspends most of the regular event handling, and only handles events in the dialog that is in exec(). This may include some UI updates (like the transitions from enabled to disabled), but I'm not positive. A better way to handle this might be to explicitly set the dialog modal, but allow the regular event loop to continue, something like this:
void Main_Screen::Create_ViPro()
{
ViPro_Dialog* modal = new ViPro_Dialog(this);
modal->setModal(true);
modal->show();
}
That code will still not visually disable the toolbar or menubar, but they should be unresponsive. To disable them, you could try combining this with Patrice Bernassola's answer.

HowTo correctly close QDialog when main windows is hidden?

I have some kind of dilemma.
I'm using:
MSVS 2008
Qt 4.7.3 (with Qt VS Add-in 1.1.9)
I wrote small Qt application, base on QMainWindow class, where also exists settings dialog (QDialog). Every works fine in GUI mode. After that I started to change my project to make it visible only in tray. Just comment in main.cpp show() method, like this:
MainWindow w;
//w.show();
return app.exec();
But from tray, I need to launch settings dialog, which is implemented in mainwindow.h/.cpp files. I added to tray menu action (QAction) which is starts that settings dialog. And here comes the unexpected problem: when I tried to close this settings dialog with [ X ] close button (in top right corner) my app closed!
Here is the action slot:
void MainWindow::onOpenSettingsDlgClicked()
{
SettingsDlg dlg( this );
dlg.exec();
}
I have tried to reimplement virtual reject() method for the settings dialog class, and set there only hide() function, but that solution not helped.
What I'm doing wrong?
Thanks you!
You should turn off the quitOnLastWindowClosed property which is turned on by default as defined in the doc (http://doc.qt.nokia.com/latest/qapplication.html#quitOnLastWindowClosed-prop)
This said, you'll have to handle the termination of your QApplication yourself, maybe with an [quit] entry in the tray menu.
Just found another option which seems better is to override closeEvent of the QDialog to only hide it.
void PrefDialog::closeEvent(QCloseEvent *event) {
this->hide();
event->ignore();
}
I found this seems better because it doesn't change the global application behaviour.

How can i check that button is clicked in no modal dialog

I created main dialog and call no modal dialog, how can i check in main dialog that button is clicked in no modal?
For example if i call modal i can check like this:
Dialog Dlg;
int DlgResult = static_cast<int>(Dlg.DoModal());
if (DlgResult== IDOK)
{
//do smth.
}
If its a custom dialog, one way would be to use SendMessage() or PostMessage() to send the result to the main dialog when the non-modal dialog closes.
Even after the window closes, you will still have access to the C++ object representing the dialog. You can override OnOK and OnCancel and have them save a flag in the object.