Forbid leaving a QLineEdit
Hi to everybody.
I know it is bad GUI programming style but I need to forbid leaving a QLineEdit if its content is not "proper".
I tried using focusOut event and inside it using setFocus but it seems is not the right thing to do. It seems that calling setFocus from inside focusOut/In events is not supported.
I'm thinking about setting a one-shot-timer to call a method to set the focus...
I read about QValidator, but I read contrasting info on this point.
Is there a way to know that a widget is about to lose focus and stop the it ?
What confuses you with the validators?
... or "Input Mask":http://doc.qt.nokia.com/stable/qlineedit.html#inputMask-prop is other kind of validation. Neither it does not help you ?
yes, you get a QEvent::FocusOut message event ...
[quote author="Volker" date="1321533645"]What confuses you with the validators?[/quote]
About validators I post the question directly:
if I'm editing a QLineEdit and for the current text the validator returns Invalid, if I press TAB/BACKTAB the focus is moved away from the QLineEdit ?
Then back to the "general" question: is it possible and if yes how, to setFocus to a QLineEdit during a focusOut/In event ?
Example, in a field I can enter the iso country codes, so I can set maximum length and force alpha chars. But I can't allow to move focus to other QLineEdits until the country code is validated !
Probably in a brand new program, following GUI guidelines, I would build the form differently, but in this case, I need to do in this way.
[quote author="BilbonSacquet" date="1321536803"]yes, you get a QEvent::FocusOut message event ... [/quote]
using setFocus in a focusOut/in event creates, in my test programs (that may be wrong) confusing situations:
- multiple blinking cursors
- cursor blinking in one QLineEdit but focus on another...
and other strangenesses..
[quote author="fp615" date="1321533645"]TAB/BACKTAB the focus is moved away from the QLineEdit ?[/quote]
It happens with or without validators.
[quote author="cincirin" date="1321538367"][quote author="fp615" date="1321533645"]TAB/BACKTAB the focus is moved away from the QLineEdit ?[/quote]
It happens with or without validators.[/quote]
Thanks for the answer, this will save me writing a test program.
Do you know about the use of setFocus inside a focusOut/In event ?
I'm not sure. Maybe your idea, with single shot timer
QTimer::singleShot(0, yourLineEdit, SLOT(setFocus()))
What about focusNextPrevChild ? in QWidget::event, when TAB/BACKTAB is pressed, focusNextPrevChild is called...
focusNextPrevChild finds the next/prev widget and calls setFocus on it.
setFocus emits focusOut and focusIn and there is no way to avoid this (well, I may override setFocus...)
I'm looking in Qt source code where focus is set after mouse click
[quote author="cincirin" date="1321538915"]I'm not sure. Maybe your idea, with single shot timer
QTimer::singleShot(0, yourLineEdit, SLOT(setFocus()))
How about you just disable the rest of your GUI elements as long as the current value is not valid? Sounds like horrible UI to me, but...
Disabling the rest of the GUI would be an option of last resort in my opinion. Most times you'll have some kind of "save" or "next" button - IMHO it would be sufficient to disable that one.
Another point to take into account: you may succeed to disable the focus, but you will not disable the other widgets, so your user can change a spinbox, check/uncheck checkboxes, select from a combobox etc. with the mouse.
Well, that was my point really. There is no way you are going to keep the user "in" the current widget, if you do not disable the other elements. As Volker sais: not all controls need focus to be usable. In linux, I think you even may be able to middle-click a line edit and paste text without the line edit having focus (I'd have to try that). And yes, it is a last resort, but at least it is clear to the user. IMHO better than restricting the user to a line edit without giving him a hint that that is the case...
But, indeed, I would stick to disabling the "Next" or "Save" or whatever your action button is, and just put a hint to the user what is wrong, and what he needs to do to enable it.
Thank you everybody for your answers.
I was finally able to obtain a consistent result, after reading Qt source code and understanding what the different events do.
So in the focusOut event I keep track that the object needs to have focus back and in the focusIn of the next widget, the first thing I do is to set focus back and returning true (so that doesn't start the blinking cursor).
I have not tried with other widgets, probably there will be no other widgets other than QLineEdit since this is a porting of a text-mode application: forms are defined in a database and so we need to comply with the text-mode forms.
Alternatively I already created a couple of tests, doing something similar to what you propose.
As you want to force your users through the line edits, I would go for another approach:
- disable every line edit but the first
- once the first line edit has acceptable input, enable the next line edit
- when the content changes to inacceptable input, disable all line edits following the current one
- and so on
This way your users have a clear presentation of which controls are usable at a given moment.
I personally would be really embarrassed by an UI that makes me widgets appear as active, which actually are not. This is against all UI design principles. Such an application is plain not acceptable from a UI point of view.