Properties and Bindings9:02 with Craig Dennis
Let's take a look at another for binding directly from the fxml file. JavaFX exposes a property pattern that handles all the event firing that you will need for two way binding.
We've seen how to dynamically change specific nodes using the FXML annotation 0:00 and by defining matching IDs. 0:05 There is a slightly more powerful way to do things. 0:07 And that is to have your FXML bind, or watch for changes and 0:09 react, to a specific property on a controller. 0:13 There are a couple benefits to doing things this way. 0:17 First, it decouples, or 0:20 removes the dependencies between the structure and the model. 0:22 Secondly, by using a property, 0:27 additional users can subscribe to its changes, and do with it what they may. 0:29 It's a little different way of looking at things than we have been. 0:35 Now usually you wouldn't see the two different styles colliding, but 0:39 I did want to expose you to this style of controller usage, so 0:43 you can make the call for yourself. 0:47 You will encounter both styles in JavaFX code and samples, so it's good for 0:49 you to get acquainted. 0:53 Ready? 0:54 Let's get binding. 0:55 So you know how we've been following that pattern of making public getter and 0:57 setter methods? 1:00 You know, the ones that start with get and start with set. 1:01 Well that pattern allows for external tools to hook into our objects. 1:05 It knows that we expose things we want to have it get and 1:09 things that we want to have it set. 1:12 Now this pattern of getters and setters is known as the Java Bean pattern. 1:14 Now you've been using it, but maybe you didn't realize it. 1:19 Now JavaFx has an additional bit to add to this pattern. 1:21 It wants you to expose a getter, a setter and a special JavaFx property object. 1:25 So, let's make one and then I'll explain it. 1:32 All right, so we want to have the text of our timer change, so 1:36 let's make one of those properties. 1:39 So they're called private and we're going to make a StringProperty. 1:41 mTimerText. 1:49 Okay and it's a javafx.beans property. 1:53 And inside of our constructor, which we don't have on this class, 1:59 let's go ahead and make a new constructor. 2:03 And we'll just make a default constructor, right. 2:08 That will be called, automatically already. 2:10 So we'll just make a new one. 2:12 And the implementation that we'll choose is called simple string properties. 2:13 So mTimerText = new SimpleStringProperty. 2:20 Okay, so let's add our getter and setter methods for the string property. 2:28 Now IntelliJ is pretty clever about it. 2:32 It knows that there's a JavaFX Bean style method. 2:33 So let's go ahead and do that. 2:36 Let's do that right below the constructor here. 2:38 We'll do, we'll construct a getter and setter for the string property mTimerText. 2:42 Okay. 2:50 And you'll see that it created getTimerText, and 2:51 it's calling mTimerText.get when you call it. 2:54 Instead of just returning the mTimerText. 2:56 It's a little bit different than what we've been seeing before 2:59 with getters and setters. 3:01 And then it also exposes this timerText suffixed with Property. 3:03 That's the new part that is required from the JavaFX Bean pattern. 3:07 And then of course there's a set. 3:13 And you'll see too, instead of just setting mTimerText, 3:14 it's calling mTimerText and it's calling set on it. 3:17 Okay, so notice how in the controller, that there's no FXML field for time. 3:21 Let's pop over to the FXML. 3:26 Go resources > FXML > home.fxml. 3:30 And we'll look at the time here. 3:33 And I'm gonna get rid of the default that's set here. 3:35 What we're gonna do is we are going to bind to that controller's property. 3:40 And the way that you do that is you use the dollar sign and 3:44 then you use the mustaches or curly braces. 3:48 And then you say controller.timerText. 3:52 And you'll see here on my screen, that there's a bug, or it's reporting a bug. 3:59 IntelliJ shows the controller in error, but it actually works, and 4:03 there's bugs filed about it. 4:06 Maybe they'll fix it here shortly. 4:07 So what happens now is that the text property on the label 4:09 is bound to the timerText property on the controller. 4:13 If we change the value of the timerText property, it will send a change event. 4:17 This event will then be captured by the label and update the text appropriately. 4:22 Pretty slick, right? 4:26 This is data binding at work. 4:27 Check the teacher's notes for more on this. 4:29 So let's test it out, right? 4:31 So let's flip back over to the constructor and let's call that set timerText Method. 4:33 So well call setTimerText. 4:40 And it's looking for a string. 4:42 So let's just put something random in there. 4:44 Let's put the word Hammer in there. 4:45 Okay? 4:47 And if we run it. 4:49 Look. Stop. 4:54 Hammer time! 4:55 And remember over in our controller over here 4:57 there is no reference at all to that time. 5:01 So it's just by setting this. 5:04 So this is a good way for 5:06 the home.fxml to say to the controller, you can't touch this. 5:08 Yes, that was a very rare MC Hammer joke double header, 5:14 and yes, they were both very dumb. 5:16 Okay. 5:19 So we wanna set that text to be the time remaining and have it tick down. 5:20 Now currently, our format is an integer though, right? 5:25 I wish there was some way that we could have a method with the same name but 5:28 worked with different parameters. 5:32 Wait, this is Java, we can. 5:34 Method overloading allows for different signatures, but the same name. 5:36 So let's make a method that takes our remaining seconds as an integer, 5:40 and then creates a nice looking format. 5:43 So let's go right underneath the set timer text, and see that one takes a string. 5:47 Let's pick one that takes an integer. 5:51 Then we'll say remainingSeconds. 5:59 Okay, so all we gotta do is a little bit of math, right? 6:03 So first let's determine what the minutes are. 6:07 That's pretty easy, right? 6:09 Remember the way you do that is we have remainingSeconds, and 6:11 that's divided by 60, that'll get us the minutes. 6:16 Remember in math those things called remainders after division happens, 6:19 you know, like, 12 divided by 7 is 1, and there's a remainder of 5. 6:23 Well, you can do that, and what that's known as in programming is a modulo. 6:26 So you use the percent sign to do that. 6:32 So let's go ahead and do that. 6:34 So we say, int seconds = 6:35 remainingSeconds % 60. 6:39 So if you divide this by 60, what's remaining afterwards, 6:44 is what that's saying. 6:47 And then we'll say setTimerText, again calling the original method, 6:51 and we'll use a String.format and we wanna make sure that there are leading zeroes. 6:57 And the way that we do that is you say 0 and at least 2. 7:04 And then you say decimal, right, so that's the %d. 7:08 But if you put 02 in there, it will pad it 2 with zeros. 7:12 And then let's do that again, %02d. 7:16 And what will happen there is we can replace those with minutes, seconds. 7:21 Right, makes sense? 7:30 So, now we can call in our prepare attempt, 7:32 we can call setTimerText = mCurrentAttempt.getRemainingSeconds. 7:38 And if we start this off, we can remove the very dumb joke where we had a hammer, 7:51 and let's just put 0 in there. 7:56 And then let's see what happens when we run it. 7:58 Perfect. So there's 0 turned into pretty string, 8:02 00:00. 8:05 Awesome. 8:06 So now you know how to create properties that when changed 8:08 send events out to all their listeners. 8:12 You also learned how to bind a property in FXML to a controller. 8:14 This is a really nice powerful pattern that JavaFX gives you out of the box. 8:19 I've added links in the teacher's notes, and I highly suggest that you get more 8:24 familiar with this powerful feature of your GUI framework. 8:28 Nice refresher on method overloading. 8:32 See how practical its use was there? 8:34 We allow anyone to pass in a string or an integer and 8:36 the timer text gets set properly. 8:40 Remember to use that method overloading trick to help make what you offer 8:43 very clear to consumers of your code. 8:47 You also learned about the modulo operator, 8:50 which is used to find the remainder of division between two numbers. 8:52 For the remainder of this course, 8:56 we're going to get this timer ticking, right after this exercise. 8:58
You need to sign up for Treehouse in order to download course files.Sign up