Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #34690 > unrolled thread
| Started by | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| First post | 2016-06-22 15:18 +0200 |
| Last post | 2016-06-23 10:56 -0400 |
| Articles | 13 — 5 participants |
Back to article view | Back to comp.lang.java.programmer
JavaFX: Bindings, StringConverters, and ChangeListeners Tassilo Horn <tsdh@gnu.org> - 2016-06-22 15:18 +0200
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Nigel Wade <nmw@ion.le.ac.uk> - 2016-06-22 15:22 +0100
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Tassilo Horn <tsdh@gnu.org> - 2016-06-23 08:39 +0200
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Martin Gregorie <martin@address-in-sig.invalid> - 2016-06-23 09:59 +0000
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Nigel Wade <nmw@ion.le.ac.uk> - 2016-06-23 12:19 +0100
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Nigel Wade <nmw@ion.le.ac.uk> - 2016-06-23 12:39 +0100
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Tassilo Horn <tsdh@gnu.org> - 2016-06-23 14:39 +0200
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Eric Douglas <e.d.programmer@gmail.com> - 2016-06-22 08:06 -0700
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Tassilo Horn <tsdh@gnu.org> - 2016-06-23 08:45 +0200
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Eric Douglas <e.d.programmer@gmail.com> - 2016-06-23 05:11 -0700
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-23 08:22 -0400
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Tassilo Horn <tsdh@gnu.org> - 2016-06-23 15:12 +0200
Re: JavaFX: Bindings, StringConverters, and ChangeListeners Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-06-23 10:56 -0400
| From | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| Date | 2016-06-22 15:18 +0200 |
| Subject | JavaFX: Bindings, StringConverters, and ChangeListeners |
| Message-ID | <87wplhbbvy.fsf@gnu.org> |
Hi all,
I'm doing my first JavaFX UI stuff and basically come along quite well.
However, there's one absurdly simple problem which I've not been able to
solve completely.
I have a TextField txtMaxTreffer whose textProperty() is bidirectionally
bound to some IntegerProperty maxTreffer using a NumberStringConverter.
txtMaxTreffer.textProperty().bindBidirectional(maxTreffer,
new NumberStringConverter());
To prevent the user from entering invalid input, the textProperty() also
has a ChangeListener that resets to the old value in case the new value
cannot be parsed to an Integer.
In general, that works just fine meaning that the user cannot enter
wrong input, and thus the NumberStringConverter which is implicitly
invoked by the binding is always able to transfer the TextField value to
the IntegerProperty.
Well, there is one situation where it doesn't work so well: When you
prepend to the input of the TextField (or the input has been empty). In
that case (and only in that case), it seems the NumberStringConverter is
invoked first and only afterwards the ChangeListener is called.
Obviously, my mechanics rely on the opposite order.
That is, let's say the textfield's value is "100" and now you prepend an
X to make the value "X100". Then the NumberStringConverter.fromString()
method gets invoked with "X100" and throws a ParseException. Then, my
ChangeListener is called and changes the invalid value back to "100".
In the other two cases where I enter the invalid input in the middle
("1X00") or at the end ("100X"), first my ChangeListener is called and
resets back to "100" before the NumberStringConverter has its turn.
Ok, the only bad effect here is that a ParseException is logged to
stderr but I guess there must be some way to make that work without
exception, too.
Of course I could provide my own NumberStringConverter which checks for
valid input before trying to parse the string to a number but then I'd
have the very same checks in both the converter and the change listener.
Any other ideas? Maybe a ChangeListener is not the right thing for
validation and correction anyhow?
Thanks,
Tassilo
[toc] | [next] | [standalone]
| From | Nigel Wade <nmw@ion.le.ac.uk> |
|---|---|
| Date | 2016-06-22 15:22 +0100 |
| Message-ID | <dsvl9oFqvv4U1@mid.individual.net> |
| In reply to | #34690 |
On 22/06/16 14:18, Tassilo Horn wrote:
> Hi all,
>
> I'm doing my first JavaFX UI stuff and basically come along quite well.
> However, there's one absurdly simple problem which I've not been able to
> solve completely.
>
> I have a TextField txtMaxTreffer whose textProperty() is bidirectionally
> bound to some IntegerProperty maxTreffer using a NumberStringConverter.
>
> txtMaxTreffer.textProperty().bindBidirectional(maxTreffer,
> new NumberStringConverter());
>
> To prevent the user from entering invalid input, the textProperty() also
> has a ChangeListener that resets to the old value in case the new value
> cannot be parsed to an Integer.
>
> In general, that works just fine meaning that the user cannot enter
> wrong input, and thus the NumberStringConverter which is implicitly
> invoked by the binding is always able to transfer the TextField value to
> the IntegerProperty.
>
> Well, there is one situation where it doesn't work so well: When you
> prepend to the input of the TextField (or the input has been empty). In
> that case (and only in that case), it seems the NumberStringConverter is
> invoked first and only afterwards the ChangeListener is called.
> Obviously, my mechanics rely on the opposite order.
>
> That is, let's say the textfield's value is "100" and now you prepend an
> X to make the value "X100". Then the NumberStringConverter.fromString()
> method gets invoked with "X100" and throws a ParseException. Then, my
> ChangeListener is called and changes the invalid value back to "100".
>
> In the other two cases where I enter the invalid input in the middle
> ("1X00") or at the end ("100X"), first my ChangeListener is called and
> resets back to "100" before the NumberStringConverter has its turn.
>
> Ok, the only bad effect here is that a ParseException is logged to
> stderr but I guess there must be some way to make that work without
> exception, too.
>
> Of course I could provide my own NumberStringConverter which checks for
> valid input before trying to parse the string to a number but then I'd
> have the very same checks in both the converter and the change listener.
>
> Any other ideas? Maybe a ChangeListener is not the right thing for
> validation and correction anyhow?
>
> Thanks,
> Tassilo
>
The first thing I'd suggest is to think about the problem from the user's perspective rather than the programmer's.
If I, as a user, enter a number into a text field and inadvertently enter an invalid character, I'd be rather annoyed if
the GUI element wiped out what I'd entered and replaced it with something which I didn't want. It would be better from
my (user) perspective if the text element warned me of my transgression (flash, highlight, red background whatever) and
left my text there for me to edit, rather than make me enter it again with the likelihood of making a similar mistake
again. Imagine if the current contents were 002324561234, and I wanted to change it to 002324560234 but instead changed
it to 00232456O234. Your current method would revert it back to 002324561234, and I may never notice that my change had
been overridden.
What's wrong with parsing the entered text and, if there is an exception, catch it and display some feedback, leaving
the focus on the text field? If you really, really want to set the text back to the original value you could still do
that in the catch block. I don't see any benefit from using a ChangeListener.
[toc] | [prev] | [next] | [standalone]
| From | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| Date | 2016-06-23 08:39 +0200 |
| Message-ID | <877fdgl87c.fsf@gnu.org> |
| In reply to | #34691 |
Nigel Wade <nmw@ion.le.ac.uk> writes: Hi Nigel, > The first thing I'd suggest is to think about the problem from the > user's perspective rather than the programmer's. > > If I, as a user, enter a number into a text field and inadvertently > enter an invalid character, I'd be rather annoyed if the GUI element > wiped out what I'd entered and replaced it with something which I > didn't want. It would be better from my (user) perspective if the > text element warned me of my transgression (flash, highlight, red > background whatever) and left my text there for me to edit, rather > than make me enter it again with the likelihood of making a similar > mistake again. Oh, flashing is actually a nice idea and can be done pretty easily from my listener. > Imagine if the current contents were 002324561234, and I wanted to > change it to 002324560234 but instead changed it to 00232456O234. Your > current method would revert it back to 002324561234, and I may never > notice that my change had been overridden. Well, in the concrete case the number is the maximum number of matches to be looked for in a database, so the numbers aren't that hard to distinguish but I got your point. > What's wrong with parsing the entered text and, if there is an > exception, catch it and display some feedback, leaving the focus on > the text field? If you really, really want to set the text back to the > original value you could still do that in the catch block. I don't see > any benefit from using a ChangeListener. The problem is that I have no control over when and where the string in the text field is parsed and converted to a number. I just specified a declarative binding between the text field's text property and an integer property with a standart converter and thereby gave up exact control over these things. But bindings are such an integral part of FX that I guessed there must be some standart way to treat invalid input so that the binding's converter doesn't err. Bye, Tassilo
[toc] | [prev] | [next] | [standalone]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2016-06-23 09:59 +0000 |
| Message-ID | <nkgbuu$l6u$1@dont-email.me> |
| In reply to | #34693 |
On Thu, 23 Jun 2016 08:39:51 +0200, Tassilo Horn wrote: > Oh, flashing is actually a nice idea and can be done pretty easily from > my listener. > Personal view: flashing is annoying if its more than a single character that's doing it. I've recently used black on white for normal Swing JTextField data entry fields and, if invalid/inappropriate/out of range, setting that to white text on red as an alert. If the rest of the window's palette is no closer to red than pastel yellow, its quite eye- catching. Actually this is numeric with the field in question being a total of several inputs. The colours I used were: - black on white = total too low - green on white = total exactly right - white on red = total too high -- martin@ | Martin Gregorie gregorie. | Essex, UK org |
[toc] | [prev] | [next] | [standalone]
| From | Nigel Wade <nmw@ion.le.ac.uk> |
|---|---|
| Date | 2016-06-23 12:19 +0100 |
| Message-ID | <dt1utmFafi7U1@mid.individual.net> |
| In reply to | #34695 |
On 23/06/16 10:59, Martin Gregorie wrote: > On Thu, 23 Jun 2016 08:39:51 +0200, Tassilo Horn wrote: > >> Oh, flashing is actually a nice idea and can be done pretty easily from >> my listener. >> > Personal view: flashing is annoying if its more than a single character > that's doing it. I've recently used black on white for normal Swing > JTextField data entry fields and, if invalid/inappropriate/out of range, > setting that to white text on red as an alert. If the rest of the > window's palette is no closer to red than pastel yellow, its quite eye- > catching. > > Actually this is numeric with the field in question being a total of > several inputs. The colours I used were: > - black on white = total too low > - green on white = total exactly right > - white on red = total too high > > You need to be careful with colours. I've had issues with UIManager overriding my colours because it decided there was insufficient contrast between the foreground and background. I'd very carefully chosen the colours so that there was sufficient contrast, but the UIManager had other ideas. As far as I could tell the UIManager only compares the light/darkness of the colours, and doesn't take proper account of the colour contrast. I have no idea if this is similar in JavaFX, my Java GUI work is with Swing. I find that a single flash is not too intrusive. It's a reasonable indication to the user that there is something wrong with the input somewhere on the dialog. Then a field highlight can be used to give feedback as to which actual field is incorrect.
[toc] | [prev] | [next] | [standalone]
| From | Nigel Wade <nmw@ion.le.ac.uk> |
|---|---|
| Date | 2016-06-23 12:39 +0100 |
| Message-ID | <dt203jFanfkU1@mid.individual.net> |
| In reply to | #34693 |
On 23/06/16 07:39, Tassilo Horn wrote: > Nigel Wade <nmw@ion.le.ac.uk> writes: > > Hi Nigel, > >> The first thing I'd suggest is to think about the problem from the >> user's perspective rather than the programmer's. >> >> If I, as a user, enter a number into a text field and inadvertently >> enter an invalid character, I'd be rather annoyed if the GUI element >> wiped out what I'd entered and replaced it with something which I >> didn't want. It would be better from my (user) perspective if the >> text element warned me of my transgression (flash, highlight, red >> background whatever) and left my text there for me to edit, rather >> than make me enter it again with the likelihood of making a similar >> mistake again. > > Oh, flashing is actually a nice idea and can be done pretty easily from > my listener. A single flash. Not flashing. > >> Imagine if the current contents were 002324561234, and I wanted to >> change it to 002324560234 but instead changed it to 00232456O234. Your >> current method would revert it back to 002324561234, and I may never >> notice that my change had been overridden. > > Well, in the concrete case the number is the maximum number of matches > to be looked for in a database, so the numbers aren't that hard to > distinguish but I got your point. It's about least surprise (and annoyance) for the user. > >> What's wrong with parsing the entered text and, if there is an >> exception, catch it and display some feedback, leaving the focus on >> the text field? If you really, really want to set the text back to the >> original value you could still do that in the catch block. I don't see >> any benefit from using a ChangeListener. > > The problem is that I have no control over when and where the string in > the text field is parsed and converted to a number. I just specified a > declarative binding between the text field's text property and an > integer property with a standart converter and thereby gave up exact > control over these things. But bindings are such an integral part of FX > that I guessed there must be some standart way to treat invalid input so > that the binding's converter doesn't err. > I don't understand what implications there are with JavaFX. A normal scenario with Java/Swing is to either check the user input when the field loses focus, is committed by key press (Return) or when the user indicates via some GUI element that the input is complete. In Swing you do this by adding listeners to the components which get notified when certain actions occur. To validate the field you would simply read the text from it and process it in whatever way you see fit. You are in full control of how and when that text is checked and how it is interpreted. You may delegate to some extent by using a JFormattedTextField, but as you are discovering that is not always the best option since you are no longer in control of when/how the field contents are interpreted. Maintaining full control is often the only option.
[toc] | [prev] | [next] | [standalone]
| From | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| Date | 2016-06-23 14:39 +0200 |
| Message-ID | <87y45wjcyr.fsf@gnu.org> |
| In reply to | #34697 |
Nigel Wade <nmw@ion.le.ac.uk> writes: >> Oh, flashing is actually a nice idea and can be done pretty easily >> from my listener. > > A single flash. Not flashing. Yes, now I'm flashing once and really like the effect. And it's good that I got my hands dirty with JavaFX animations thereby. >> The problem is that I have no control over when and where the string >> in the text field is parsed and converted to a number. I just >> specified a declarative binding between the text field's text >> property and an integer property with a standart converter and >> thereby gave up exact control over these things. But bindings are >> such an integral part of FX that I guessed there must be some >> standart way to treat invalid input so that the binding's converter >> doesn't err. >> > > I don't understand what implications there are with JavaFX. A normal > scenario with Java/Swing is to either check the user input when the > field loses focus, is committed by key press (Return) or when the user > indicates via some GUI element that the input is complete. Yes, right. But with JavaFX, once you have established a binding between a UI input control and a property, the synchronization seems to happen immediately, that is, it doesn't wait for a loss of focus or some special confirmation like pressing enter. Bye, Tassilo
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2016-06-22 08:06 -0700 |
| Message-ID | <cf173549-4d73-4f6a-9d3f-031a070ce34c@googlegroups.com> |
| In reply to | #34690 |
On Wednesday, June 22, 2016 at 9:18:19 AM UTC-4, Tassilo Horn wrote: > To prevent the user from entering invalid input, the textProperty() also > has a ChangeListener that resets to the old value in case the new value > cannot be parsed to an Integer. Revert to old value? You don't want a user to be able to type something and see what they typed then change it on them. I don't know much about Java FX, I write Swing and have only needed the FX for the WebView, but for a numeric entry allowing only valid numbers I've used JTextField with a custom input filter. The input filters process every character they try to add to or remove from the control before adding or removing it.
[toc] | [prev] | [next] | [standalone]
| From | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| Date | 2016-06-23 08:45 +0200 |
| Message-ID | <8737o4l7xo.fsf@gnu.org> |
| In reply to | #34692 |
Eric Douglas <e.d.programmer@gmail.com> writes: Hi Eric, >> To prevent the user from entering invalid input, the textProperty() >> also has a ChangeListener that resets to the old value in case the >> new value cannot be parsed to an Integer. > > Revert to old value? Revert to old value in this case basically means the user types a key and the value does not change. > You don't want a user to be able to type something and see what they > typed then change it on them. Well, I think in this case it's not too bad, especially if the field flashes when invalid input is entered. > I don't know much about Java FX, I write Swing and have only needed > the FX for the WebView, but for a numeric entry allowing only valid > numbers I've used JTextField with a custom input filter. The input > filters process every character they try to add to or remove from the > control before adding or removing it. Yes, that's what I did in Swing, too. And the FX ChangeListeners are not too different. At least, they are called on any key the user typed into the text field. My problem is more on the part on when the binding's string-to-integer converter is invoked. When entering text in the middle or end, it'll be called after my listener (good!) but when entering text at the front, it'll be called before my listener (bad!). Bye, Tassilo
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2016-06-23 05:11 -0700 |
| Message-ID | <cfe580ca-be4d-48db-9cdb-6ae8d059511c@googlegroups.com> |
| In reply to | #34694 |
On Thursday, June 23, 2016 at 2:45:49 AM UTC-4, Tassilo Horn wrote: > Yes, that's what I did in Swing, too. And the FX ChangeListeners are > not too different. At least, they are called on any key the user typed > into the text field. My problem is more on the part on when the > binding's string-to-integer converter is invoked. When entering text in > the middle or end, it'll be called after my listener (good!) but when > entering text at the front, it'll be called before my listener (bad!). It should be more than key typed. The input filters for JTextField give you character added or removed event which could be a key type, copy/paste, or drag/drop. This should happen before any listeners. I write custom controls extending Swing GUI which have their own listeners. I add a listener interface array so I can manually tell my custom listeners when an event has occurred. I had some issues with JTable returning the events in an odd order, so I'd store an event which normally follows another event and pass it to the listeners after I get the other event.
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2016-06-23 08:22 -0400 |
| Message-ID | <nkgkao$k1b$1@dont-email.me> |
| In reply to | #34698 |
On 6/23/2016 8:11 AM, Eric Douglas wrote:
> On Thursday, June 23, 2016 at 2:45:49 AM UTC-4, Tassilo Horn wrote:
>> Yes, that's what I did in Swing, too. And the FX ChangeListeners are
>> not too different. At least, they are called on any key the user typed
>> into the text field. My problem is more on the part on when the
>> binding's string-to-integer converter is invoked. When entering text in
>> the middle or end, it'll be called after my listener (good!) but when
>> entering text at the front, it'll be called before my listener (bad!).
>
> It should be more than key typed. The input filters for JTextField give you character added or removed event which could be a key type, copy/paste, or drag/drop. This should happen before any listeners.
>
> I write custom controls extending Swing GUI which have their own listeners. I add a listener interface array so I can manually tell my custom listeners when an event has occurred. I had some issues with JTable returning the events in an odd order, so I'd store an event which normally follows another event and pass it to the listeners after I get the other event.
FWIW, in Swing applications I've had good experiences with using
an InputVerifier. Or, perhaps, "misusing" it: I don't use the verify()
method at all, but override shouldYieldFocus() instead. If the content
is invalid, my shouldYieldFocus() returns false and the user quickly
discovers that he's stuck in the field until he corrects it.
I'm not FXliterate, so I don't know whether there's an analog.
Could be worth a look, though.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | Tassilo Horn <tsdh@gnu.org> |
|---|---|
| Date | 2016-06-23 15:12 +0200 |
| Message-ID | <87twgkjbge.fsf@gnu.org> |
| In reply to | #34700 |
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> FWIW, in Swing applications I've had good experiences with using
> an InputVerifier.
Yes, that works fine in Swing...
> I'm not FXliterate, so I don't know whether there's an analog.
> Could be worth a look, though.
... but there doesn't seem to be something similar in FX. Googling
suggests that input validation is currently one the missing pieces in FX
and it seems that right now everybody uses a FocusListener to validate
the input when the control loses focus.
Well, never mind, I've simply stopped using a bidirectional binding with
a number-string-converter and just use
maxTreffer.bind(Bindings.createIntegerBinding(() -> {
String txt = txtMaxTreffer.getText();
try {
return Integer.valueOf(txt);
} catch(NumberFormatException ignored) { }
return maxTreffer.get();
}, txtMaxTreffer.textProperty()));
Thanks for all suggestions,
Tassilo
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2016-06-23 10:56 -0400 |
| Message-ID | <nkgtbj$kba$1@dont-email.me> |
| In reply to | #34702 |
On 6/23/2016 9:12 AM, Tassilo Horn wrote:
>[...]
> ... but there doesn't seem to be something similar in FX. Googling
> suggests that input validation is currently one the missing pieces in FX
A *user* *interface* framework without input validation?
YIKES!
No wonder Oracle is so keen about Ineffectual Property ...
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web