In Qt5.2.1 I am setting the input mask of a QLineEdit object as follows:
pLineEdit->setInputMask("009.9;_");
This should mean that the first two digits 0-9 can be present but are not mandatory, then a digit 0-9 followed by dot (.) followed by another digit 0-9 are required, and finally the blank character is replaced with _ when editing (the final ";_").
Then I set the content with:
pLineEdit->setText("40.0");
So I would expect to see in the line edit the following:
40.0
but I read instead this:
40_.0
What could be the problem?
Note: the OP is probably having an XY problem, yet it may be interesting to provide some insights about the specific problem at hand, even though using the proper approach should be preferred instead.
Based on your question and comment, I'm inclined to think that you are just using the wrong class.
The input mask of QLineEdit is mostly intended to enter and display arbitrary alphanumeric contents; even though the contents may be based on numeric values, it normally makes sense only when the entered/displayed contents are complex ones.
If you need a field that should contain one numeric object (in the sense of a single object reflecting a numeric value, such as an integer or a float), then you should opt for QSpinBox and QDoubleSpinBox instead.
If you need a floating point object, then use QDoubleSpinBox, and eventually set its decimals
property based on your needs.
If you don't want the up/down arrows, then set the buttonSymbols
property of the base class (QAbstractSpinBox) to QAbstractSpinBox::NoButtons
.
Note that this will potentially give an entry field that requires a minimum width larger than required (some styles always consider the minimum width including the buttons, even if they're not shown). There can be ways of working around this issue, but I'll leave that to another question.
An important thing to be aware of is that QLineEdit doesn't treat "lightly" its text
property: both its getter and setter functions actually behave differently in some cases.
Almost all text based widgets in Qt use an internal/private "control" class, which is "QWidgetLineControl" for QLineEdit.
Depending on the context, setText()
may not set the exact string used as its argument, as well as text()
may not return the same string. Also, the result of text()
and displayText()
may differ and look inconsistent/unexpected.
In your case, doing setText("40.0")
will return "40.0"
for text()
and "40_.0"
for displayText()
(as seen on screen).
Furthermore, doing an inappropriate setText("4.a")
will return "4."
and "4__._"
respectively: the "a" is completely ignored.
The above seems inconsistent with the given mask (which would require valid numeric contents for the third character), but it's still allowed by the "mask engine" due to a "forgiveness" implementation that considers temporarily acceptable entries.
setText()
callsThe input mask implementation doesn't consider the validity of the full entry at once: key presses, clipboard pasting and setText()
calls would only verify the entered text based on the input context and mask, while "temporarily" allowing an invalid entry.
The behavior is similar to a QValidator returning Intermediate
(hence, not Invalid
, but also not Acceptable
).
In fact, doing setText("40.0")
will result in false
from hasAcceptableInput()
, even though text()
may seem valid.
If you really need a QLineEdit object following that input mask, then you should call setText()
considering the input mask structure and the "blank character".
In the case at hand, the proper call should be:
pLineEdit->setText("_40.0");
The above will return true
from hasAcceptableInput()
. The result is similar as in trying to input the same exact text with the keyboard.
The reasoning is that a text-input widget such as QLineEdit should allow temporary editing, even though some "fields" may invalid while editing: typing the "4", "0", ".", "0" sequence is a temporary, intermediate and acceptable entry, allowing the user to further edit character entries after that.
As written in the premise, if you just need an UI field used for a single numeric object (an integer or a float), then you should use the proper classes (QSpinBox and QDoubleSpinBox, respectively).
If the above requirement and behavior doesn't match your need, then you must consider the implementation of the input mask: setting it isn't just enough, and you should consider its behavior both when setting and getting the text value.
QLineEdit (as much as any class using it, including QAbstractSpinBox based classes) also provides a setValidator()
function that can implement (or even expand) such requirements.
If you want to edit/display a float and really don't want a QDoubleSpinBox, you can still use QLineEdit along with QDoubleValidator.
Just be aware that there are some unexpected (yet known but not easily fixable) issues with such validation systems, as typing doesn't really play well with complex validation of numeric ranges.
For instance, consider the case of an UI element that only accepts entries between 11 and 20: typing "1" on an empty field would be acceptable, even though that value wouldn't be valid unless any number above 0 is typed after that or 1 is typed before it.