• Post Reply Bookmark Topic Watch Topic
  • New Topic

Bind a string directly to a label?  RSS feed

 
Michael D Sims
Ranch Hand
Posts: 113
1
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Goggled for a while ... and all kinds of stuff out there, but nothing that specifically addresses what I would LIKE to do.
I just want to bind a string to a label so that when the string changes, the label changes automagically. Like this:

So far, the only thing I could find that actually worked, was by using the SimpleStringProperty class, like this:
THE PROBLEM with that setup, is that folder is no longer a String, and to set it's value, I have to do it like this:

Which is LAME, I want to use the String like a string and just have it update the label ... why is this seemingly impossible?

Thank you,

Mike Sims
 
Paul Clapham
Sheriff
Posts: 22834
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But Strings never change -- they are immutable. I suppose you really mean that you want to change the contents of the label whenever the variable which refers to the String is changed (to refer to some other String). And no, there's nothing in Java which lets you do that.

What you have there in the rest of the post is the normal way to do things.
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please explain exactly what you want to do. Are you using that Property in lieu of a field in some object or other? And what do you want to bind it to?
It might be possible to bind your property to another property after all. It would have to be bound to a property of the same type, but you can doubtless use something like textProperty() on your Label.

By the way: Have you found a decent tutorial about JavaFX properties?
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Any progress telling us what you are trying to do?
 
Michael D Sims
Ranch Hand
Posts: 113
1
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Please explain exactly what you want to do.

OK, it's quite simple really ... I have a button with the words 'chose a folder' on it... the user clicks on the button and they chose a folder. The folder path they end up chosing gets set to a String ... there is a label next to the button. I just wanted to have that label bound to the string so that when the folder path changes, the label shows the currently selected path.

:-)

I realize im splitting hairs and that I'm kinda just trying to be lazy about it ... As I could just as easily assign the text to the label at the same time I assign it to the String ... but Java kinda started out with this whole concept of being able to bind objects to other objects ... as somewhat of a Java special skill ... so I felt it should be a relatively simple thing to do ...  but you know what they say about assumptions ... ;-)
 
Michael D Sims
Ranch Hand
Posts: 113
1
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:But Strings never change -- they are immutable

Surely you're stating this as matter of 'best practice' and NOT as a literal fact concerning Java itself ... cause I change the value of Strings regularly in my code ... and if you're saying that it literally won't work ... then Im gonna start freaking out wondering how I've been getting away with this all this time ... ;-)
 
Dave Tolls
Ranch Foreman
Posts: 3065
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
They are immutable, as Paul says.
The following does not change any String object:

it simply changes the object that the 's' variable is referring to.
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So, you click your button, choose a folder by some means not at present specified, and the text on the label changes.
You can add a Listener to the label, but it will need an Observable instance to (would you believe) observe. So a Label has a textProperty() method actually inherited from a superclass. You call that method and you get access to a StringProperty called text or textProperty. That is an ObservableValue, and that means it implements an addListener(ChangeListener) method. I think you can create a ChangeListener as a λ something like
myStringProperty.addListener((myOtherObservable, oldValue, newValue) -> this.set(myOtherObservable.getText()));
You might need to put a ; after the underlined code and wrap it in {}.
I am not certain that I have given you the right syntax, but don't have the time to check it now.
 
John Damien Smith
Ranch Hand
Posts: 357
22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As an aside here is a StackOverflow explanation for Java string immutability to help understand the concept:
  http://stackoverflow.com/questions/1552301/immutability-of-strings-in-java

From the Java language reference:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.3.3

4.3.3. The Class String

Instances of class String represent sequences of Unicode code points.

A String object has a constant (unchanging) value.

String literals (§3.10.5) are references to instances of class String.

The string concatenation operator + (§15.18.1) implicitly creates a new String object when the result is not a constant expression (§15.28).

https://docs.oracle.com/javase/specs/jls/se8/html/jls-10.html#jls-10.9

10.9. An Array of Characters Is Not a String

In the Java programming language, unlike C, an array of char is not a String, and neither a String nor an array of char is terminated by '\u0000' (the NUL character).

A String object is immutable, that is, its contents never change, while an array of char has mutable elements.

The method toCharArray in class String returns an array of characters containing the same character sequence as a String. The class StringBuffer implements useful methods on mutable arrays of characters.


As strings are immutable and cannot change, you cannot bind a string to a label which could change nor could you bind label text to a string which could change, that would not make sense.
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Short of a shared mutable object, it would be difficult to implement such a functionality. You could have a wrapper class round a String which changes its text. But you cannot alter the state of the String instance; you can only replace it with a different String instance. There are all sorts of advantages to making Strings immutable including reduced memory consumption, thread‑safety, and the ability to share Strings. But it makes it impossible to have a shared String reference and have changes in one place follow changes in another. So you design the observer pattern. Briefly you hava an observee which would implement the Observable interface or extend the Observable class. Note that the label doesn't implement either. It is the property which implements Observable. I suspect that the Observable interface is a better design than the Observable class, because of single inheritance, so you can use Observable as a mixin interface. That may be because the JavaFX packages are newer than java.util.
Now whenever something happens to an Observable, it starts signalling (well, firing change event objects) that something has happened. Now you need an Observer, implementing this interface or by using this sort of method to add an appropriate Listener to whatever is observing it. So whenever there is a change, you fire the method listening for that change. If you go through the change listener link, you will see the single method takes three parameters, the observee (observable), its old value and its new value. Don't call the newValue argument new because that is a keyword. There is nothing new about this pattern. You will notice that a string property will add a ChangeListener<String> so the parameters will be Strings or Observable<String>.

And that is how you can use the Observer pattern to implement what you want

Anybody know whether that Observable interface and the change listener are generally applicable, or whether they are specific to JavaFX?
 
John Damien Smith
Ranch Hand
Posts: 357
22
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
While you could implement an Observable interface as outlined by Campbell Ritchie, you don't need to do that (at least if I understood what he was writing which perhaps i didn't ;-).  That's like implementing things from first principles, which is useful in really understanding concepts but not really necessary here.  StringProperty already exists in JavaFX and it already implements an Observable interface.  So the JavaFX developers have already done all of the work of implementing all of the patterns that Campbell Ritchie outlines.

In fact, the original code your wrote in your question is the recommended way of establishing bindings of string based data. 

If using rather than causes you dislike due to the verbosity, then you might like to look into something like ScalaFX or the Kotlin based TornadoFX, which use some tricks unique to their language base to allow you to use the assignment operator rather than a set method to invoke a JavaFX property setter.  However, as you seem to just be getting started with JavaFX, I would advise sticking with Java until you are more comfortable with JavaFX development in Java before attempting JavaFX development in another language.

> Java kinda started out with this whole concept of being able to bind objects to other objects ... as somewhat of a Java special skill

Actually it didn't.  Java as a language does not have binding within it (you won't find it mentioned in the Java language specification).  The binding logic has been added via later JRE implementations as API libraries.  The binding and property implementation in JavaFX only became a part of the Oracle JRE distribution a few years ago and is still not shipped with many non-Oracle JRE distributions.  No Java Specification Request has been filed to make the JavaFX property implementation a part of the JRE for non-Oracle java vendors, though, as I understand it, there is an intent to file a specification request at some date in the future.  Nevertheless, as long as you are using Oracle JRE or an OpenJDK implementation which includes a JavaFX build, then the JavaFX property implementations will work. 

> Anybody know whether that Observable interface and the change listener are generally applicable, or whether they are specific to JavaFX

I assume you refer to javafx.beans.Observableand not java.util.Observable.

The JavaFX Observable and ChangeListener interfaces are currently specific to JavaFX (see above).  However, as long as the JavaFX libraries are present in the JRE that you are using as your runtime, then you can use the JavaFX binding and property systems from any Java program (i.e. they don't require the JavaFX system to be initialized or that your application inherit javafx.application.Application).  The prototypical tutorial for Java bindings from Oracle does not use JavaFX applications at all while using properties and bindings.

I recall one of the JavaFX the developers who created the binding and property system as well as the transition, animation and timeline systems, mentioned that the design was to have those systems implemented and useable outside of the JavaFX GUI libraries.  I think they managed to achieve that for bindings and properties but not for transition, animation and timeline (which I think may have ended up tied to some hardware clock and native screen refresh rate detection code).  So, perhaps in Java 9 or 10 it will be possible to use a modular JDK which includes modules for JavaFX properties and bindings, but not the whole JavaFX GUI toolkit.

If interested in potential applications of JavaFX properties outside of a JavaFX client app, see: http://www.marshall.edu/genomicjava/2014/05/09/one-bean-to-bind-them-all/

-----

Aside:  If you have model classes that implement standard plain java beans getters and setters but do not fire changes because they don't implement PropertyChangeListener (very common situation), you can make use of a javafx.beans.property.adapter.JavaBeanStringProperty which "provides an adapter between a regular Java Bean property of type String and a JavaFX StringProperty".  I have not seen much use of the adapter classes in code and they are not well documented.
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
John Damien Smith wrote:. . .  So the JavaFX developers have already done all of the work of implementing all of the patterns that Campbell Ritchie outlines.
Good point. I think I knew that but didn't write it last night.
. . . > Anybody know whether that Observable interface and the change listener are generally applicable, or whether they are specific to JavaFX

I assume you refer to javafx.beans.Observableand not java.util.Observable. . . . as long as the JavaFX libraries are present in the JRE that you are using as your runtime, then you can use the JavaFX binding and property systems from any Java program . . . .
Yes, I meant the Observable interface not the class in java.util. That is useful information (thank you ), which I don't have the time to explore this week, but I shall look at later. I remember Cai Horstmann writing somewhere about “properties, like in C#, but better.” It is a very long time since I tried any C# but I think they may have succeeded there
Your post merits some very raw beef.
 
Michael D Sims
Ranch Hand
Posts: 113
1
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you, everyone, for taking the time to comment on this.

As it turns out, I stayed with the StringProperty class, binding it to the Labels textProperty, then using the setValue method of the StringProperty. Now that I understand how the classes involved work, it makes perfect sense to do it this way.

Sincerely,

Mike Sims
 
Campbell Ritchie
Marshal
Posts: 56570
172
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well done and thank you for an interesting question.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!