Click outside dialog to dismiss
-
If you use a
QDateEdit
and setQDateEdit::setCalendarPopup(true)
, you get a calendar popup, and if user clicks outside of the popup/widget it auto-closes, without selecting a date.This behaviour is ideal. However, for reasons about limitations discussed in a post elsewhere, I am not able to use this widget. Instead I have had to "roll my own" --- a
QLineEdit
plus aQPushButton
, clicking the button brings up a modal dialog containing just aQCalendarWidget
, picking a date copies it to the line edit. In itself this works fine.However, I would like to improve the usability of this "composite widget" such that if the user simply clicks outside of the popup dialog it gets dismissed, without the user having to click its close button (so it's like the
QDateEdit
widget).How would I do this, simply?
I'm assuming it won't work with a modal dialog as it won't be easy to react to a click outside of the dialog? So I'm thinking:
- Make the dialog modeless.
- React to a click on the parent dialog/window/widget, which is outside of the modeless popop.
Is this what I will need? (Unless there's another "popup window" style I could use which would do this automatically?) What code will I need to recognise the mouse-click on the parent outside of the popup to initiate the dismiss? At present (because the dialog is modal) all the code to handle the popup is perfectly isolated in the "composite widget" which pops up the dialog. Will the new code have to have the parent window/widget know that it has such a child widget to deal with the "click outside", which is a shame?
-
@mpergand said in Click outside dialog to dismiss:
Have you tried :
setWindowFlags(Qt::Popup);
What did you, or the person who up-voted this, expect this to do? I got excited, but it seems to have no discernible effect. Certainly it did not make it so the dialog is dismissed when I click outside of it. From http://doc.qt.io/qt-5/qt.html#WindowType-enum I read it as purely a decorative/visual effect.
EDIT: Whoa, see end of this post...
Hmm, I came across https://stackoverflow.com/questions/7421699/close-widget-window-if-mouse-clicked-outside-of-it. Which looks like mine, and two answers do indeed suggest
setWindowFlags(Qt::Popup)
(although it seems to me the docs say nothing about behaviour). However, this does not dismiss for me; I'm on Linux/Ubuntu/GNOME , don't know if that makes it not work...? Ahhh, I see https://stackoverflow.com/a/7432661/489865 comments:In Qt 4.8 this technique stops working. Works well for 4.7.4 though.
It seems not work in Qt 5.3.1 alsoEDIT:
Whoa, let's start again with theQt::Popup
recommendation!My code had read:
self.setWindowFlags(self.windowFlags() | Qt.Popup)
I always do
setWindowFlags()
ORing in new flags over what's already there, 'coz I don't know whether something else there is wanted. Just before abandoning, I tried:self.setWindowFlags(Qt.Popup)
and, lo & behold, it works!
-
@mpergand said in Click outside dialog to dismiss:
Have you tried :
setWindowFlags(Qt::Popup);
What did you, or the person who up-voted this, expect this to do? I got excited, but it seems to have no discernible effect. Certainly it did not make it so the dialog is dismissed when I click outside of it. From http://doc.qt.io/qt-5/qt.html#WindowType-enum I read it as purely a decorative/visual effect.
EDIT: Whoa, see end of this post...
Hmm, I came across https://stackoverflow.com/questions/7421699/close-widget-window-if-mouse-clicked-outside-of-it. Which looks like mine, and two answers do indeed suggest
setWindowFlags(Qt::Popup)
(although it seems to me the docs say nothing about behaviour). However, this does not dismiss for me; I'm on Linux/Ubuntu/GNOME , don't know if that makes it not work...? Ahhh, I see https://stackoverflow.com/a/7432661/489865 comments:In Qt 4.8 this technique stops working. Works well for 4.7.4 though.
It seems not work in Qt 5.3.1 alsoEDIT:
Whoa, let's start again with theQt::Popup
recommendation!My code had read:
self.setWindowFlags(self.windowFlags() | Qt.Popup)
I always do
setWindowFlags()
ORing in new flags over what's already there, 'coz I don't know whether something else there is wanted. Just before abandoning, I tried:self.setWindowFlags(Qt.Popup)
and, lo & behold, it works!
@JonB said in Click outside dialog to dismiss:
lo & behold, it works!
Hi
So why don't you put this topic as "Solved", and give your helper a thumbs up? -
@JonB said in Click outside dialog to dismiss:
lo & behold, it works!
Hi
So why don't you put this topic as "Solved", and give your helper a thumbs up?@Diracsbracket
...because I'm still in the middle of editing my comment, as I have been doing all morning...?If you look I think you'll see I never fail to mark as solved, and always mark other posters with thanks where possible. Give me a chance! :)
-
@Diracsbracket
...because I'm still in the middle of editing my comment, as I have been doing all morning...?If you look I think you'll see I never fail to mark as solved, and always mark other posters with thanks where possible. Give me a chance! :)
-
Right.
I have done a "thumbs up" on @mpergand's
setWindowFlags(Qt::Popup);
post.Just before I mark this thread as solved, I am trying to make the resulting popup window centered, or "close to", the button the user has pressed which causes the popup window to appear (as is the case in
QDateEdit
). Although I have set the button as the popup window's parent, the popup still appears in the center of the parent dialog as a whole. Do I perchance need to do my own geometry calls & manipulation for this? -
OK, to try to finish off (and mark as "Solved"!). I am having trouble writing the correct/simple code for placing the popup window/dialog relative to the button which is clicked to pop it up.
The hierarchy I have is:
- A dialog
- A "composite" widget on the dialog (line edit + button)
- A button on the widget
After much experimentation, I have come up with (
self
is the "composite" widget):pos = self.button.pos() # button on widget pos += self.pos() # widget on dialog pos += self.parent().pos() # widget parent (dialog) self.popup.move(pos)
This is approximately right (I think it's still out by the title bar of the dialog). I'm aware this does not "scale", in that it relies on knowing the layout/parentage, which it should not do.
How are you supposed to just get the right kind of coordinates for some button somewhere (could be down many levels of parentage) on some dialog, such that you can use that button as the top-left of a popup dialog you're just about to display? There must be a more accurate/simpler/robust solution.
If I don't get a reply to that in this thread, I guess I could open a new thread...
EDIT: OK, by trial, error, and a little peeking at source code:
pos = self.button.rect().topLeft() pos = self.button.mapToGlobal(pos) self.dialog.move(pos)
-
For anyone who found this on Google and like me OP's suggestion to completely overwrite window flags did not work, wrapping the widget in a QDialog with Qt::Popup set did work.