1 00:00:00,250 --> 00:00:05,110 We've seen how to dynamically change specific nodes using the FXML annotation 2 00:00:05,110 --> 00:00:07,100 and by defining matching IDs. 3 00:00:07,100 --> 00:00:09,480 There is a slightly more powerful way to do things. 4 00:00:09,480 --> 00:00:13,860 And that is to have your FXML bind, or watch for changes and 5 00:00:13,860 --> 00:00:16,730 react, to a specific property on a controller. 6 00:00:17,940 --> 00:00:20,750 There are a couple benefits to doing things this way. 7 00:00:20,750 --> 00:00:22,370 First, it decouples, or 8 00:00:22,370 --> 00:00:26,460 removes the dependencies between the structure and the model. 9 00:00:27,670 --> 00:00:29,950 Secondly, by using a property, 10 00:00:29,950 --> 00:00:34,060 additional users can subscribe to its changes, and do with it what they may. 11 00:00:35,820 --> 00:00:39,700 It's a little different way of looking at things than we have been. 12 00:00:39,700 --> 00:00:43,790 Now usually you wouldn't see the two different styles colliding, but 13 00:00:43,790 --> 00:00:47,200 I did want to expose you to this style of controller usage, so 14 00:00:47,200 --> 00:00:48,460 you can make the call for yourself. 15 00:00:49,490 --> 00:00:53,890 You will encounter both styles in JavaFX code and samples, so it's good for 16 00:00:53,890 --> 00:00:54,840 you to get acquainted. 17 00:00:54,840 --> 00:00:55,750 Ready? 18 00:00:55,750 --> 00:00:56,340 Let's get binding. 19 00:00:57,610 --> 00:01:00,880 So you know how we've been following that pattern of making public getter and 20 00:01:00,880 --> 00:01:01,990 setter methods? 21 00:01:01,990 --> 00:01:05,050 You know, the ones that start with get and start with set. 22 00:01:05,050 --> 00:01:09,090 Well that pattern allows for external tools to hook into our objects. 23 00:01:09,090 --> 00:01:12,230 It knows that we expose things we want to have it get and 24 00:01:12,230 --> 00:01:14,230 things that we want to have it set. 25 00:01:14,230 --> 00:01:19,045 Now this pattern of getters and setters is known as the Java Bean pattern. 26 00:01:19,045 --> 00:01:21,660 Now you've been using it, but maybe you didn't realize it. 27 00:01:21,660 --> 00:01:25,650 Now JavaFx has an additional bit to add to this pattern. 28 00:01:25,650 --> 00:01:31,710 It wants you to expose a getter, a setter and a special JavaFx property object. 29 00:01:32,750 --> 00:01:36,040 So, let's make one and then I'll explain it. 30 00:01:36,040 --> 00:01:39,220 All right, so we want to have the text of our timer change, so 31 00:01:39,220 --> 00:01:41,520 let's make one of those properties. 32 00:01:41,520 --> 00:01:47,305 So they're called private and we're going to make a StringProperty. 33 00:01:49,910 --> 00:01:50,410 mTimerText. 34 00:01:53,700 --> 00:01:56,530 Okay and it's a javafx.beans property. 35 00:01:59,090 --> 00:02:03,530 And inside of our constructor, which we don't have on this class, 36 00:02:03,530 --> 00:02:06,180 let's go ahead and make a new constructor. 37 00:02:08,670 --> 00:02:10,630 And we'll just make a default constructor, right. 38 00:02:10,630 --> 00:02:12,870 That will be called, automatically already. 39 00:02:12,870 --> 00:02:13,758 So we'll just make a new one. 40 00:02:13,758 --> 00:02:20,450 And the implementation that we'll choose is called simple string properties. 41 00:02:20,450 --> 00:02:26,020 So mTimerText = new SimpleStringProperty. 42 00:02:28,550 --> 00:02:32,110 Okay, so let's add our getter and setter methods for the string property. 43 00:02:32,110 --> 00:02:33,960 Now IntelliJ is pretty clever about it. 44 00:02:33,960 --> 00:02:36,430 It knows that there's a JavaFX Bean style method. 45 00:02:36,430 --> 00:02:38,150 So let's go ahead and do that. 46 00:02:38,150 --> 00:02:42,590 Let's do that right below the constructor here. 47 00:02:42,590 --> 00:02:50,020 We'll do, we'll construct a getter and setter for the string property mTimerText. 48 00:02:50,020 --> 00:02:51,260 Okay. 49 00:02:51,260 --> 00:02:54,120 And you'll see that it created getTimerText, and 50 00:02:54,120 --> 00:02:56,920 it's calling mTimerText.get when you call it. 51 00:02:56,920 --> 00:02:59,190 Instead of just returning the mTimerText. 52 00:02:59,190 --> 00:03:01,950 It's a little bit different than what we've been seeing before 53 00:03:01,950 --> 00:03:03,340 with getters and setters. 54 00:03:03,340 --> 00:03:07,860 And then it also exposes this timerText suffixed with Property. 55 00:03:07,860 --> 00:03:13,400 That's the new part that is required from the JavaFX Bean pattern. 56 00:03:13,400 --> 00:03:14,790 And then of course there's a set. 57 00:03:14,790 --> 00:03:17,600 And you'll see too, instead of just setting mTimerText, 58 00:03:17,600 --> 00:03:19,809 it's calling mTimerText and it's calling set on it. 59 00:03:21,270 --> 00:03:25,830 Okay, so notice how in the controller, that there's no FXML field for time. 60 00:03:26,970 --> 00:03:28,550 Let's pop over to the FXML. 61 00:03:30,460 --> 00:03:33,260 Go resources > FXML > home.fxml. 62 00:03:33,260 --> 00:03:35,180 And we'll look at the time here. 63 00:03:35,180 --> 00:03:38,300 And I'm gonna get rid of the default that's set here. 64 00:03:40,260 --> 00:03:44,830 What we're gonna do is we are going to bind to that controller's property. 65 00:03:44,830 --> 00:03:48,422 And the way that you do that is you use the dollar sign and 66 00:03:48,422 --> 00:03:51,330 then you use the mustaches or curly braces. 67 00:03:52,590 --> 00:03:59,060 And then you say controller.timerText. 68 00:03:59,060 --> 00:04:03,585 And you'll see here on my screen, that there's a bug, or it's reporting a bug. 69 00:04:03,585 --> 00:04:06,140 IntelliJ shows the controller in error, but it actually works, and 70 00:04:06,140 --> 00:04:07,890 there's bugs filed about it. 71 00:04:07,890 --> 00:04:09,730 Maybe they'll fix it here shortly. 72 00:04:09,730 --> 00:04:13,090 So what happens now is that the text property on the label 73 00:04:13,090 --> 00:04:16,420 is bound to the timerText property on the controller. 74 00:04:17,740 --> 00:04:22,850 If we change the value of the timerText property, it will send a change event. 75 00:04:22,850 --> 00:04:26,520 This event will then be captured by the label and update the text appropriately. 76 00:04:26,520 --> 00:04:27,470 Pretty slick, right? 77 00:04:27,470 --> 00:04:29,120 This is data binding at work. 78 00:04:29,120 --> 00:04:30,540 Check the teacher's notes for more on this. 79 00:04:31,620 --> 00:04:33,330 So let's test it out, right? 80 00:04:33,330 --> 00:04:40,380 So let's flip back over to the constructor and let's call that set timerText Method. 81 00:04:40,380 --> 00:04:42,720 So well call setTimerText. 82 00:04:42,720 --> 00:04:44,100 And it's looking for a string. 83 00:04:44,100 --> 00:04:45,410 So let's just put something random in there. 84 00:04:45,410 --> 00:04:46,870 Let's put the word Hammer in there. 85 00:04:47,970 --> 00:04:48,470 Okay? 86 00:04:49,610 --> 00:04:51,800 And if we run it. 87 00:04:54,730 --> 00:04:55,670 Look. Stop. 88 00:04:55,670 --> 00:04:56,170 Hammer time! 89 00:04:57,530 --> 00:05:01,200 And remember over in our controller over here 90 00:05:01,200 --> 00:05:04,510 there is no reference at all to that time. 91 00:05:04,510 --> 00:05:06,920 So it's just by setting this. 92 00:05:06,920 --> 00:05:08,140 So this is a good way for 93 00:05:08,140 --> 00:05:12,880 the home.fxml to say to the controller, you can't touch this. 94 00:05:14,090 --> 00:05:16,770 Yes, that was a very rare MC Hammer joke double header, 95 00:05:16,770 --> 00:05:19,480 and yes, they were both very dumb. 96 00:05:19,480 --> 00:05:20,330 Okay. 97 00:05:20,330 --> 00:05:25,200 So we wanna set that text to be the time remaining and have it tick down. 98 00:05:25,200 --> 00:05:28,030 Now currently, our format is an integer though, right? 99 00:05:28,030 --> 00:05:32,590 I wish there was some way that we could have a method with the same name but 100 00:05:32,590 --> 00:05:34,560 worked with different parameters. 101 00:05:34,560 --> 00:05:36,510 Wait, this is Java, we can. 102 00:05:36,510 --> 00:05:40,000 Method overloading allows for different signatures, but the same name. 103 00:05:40,000 --> 00:05:43,110 So let's make a method that takes our remaining seconds as an integer, 104 00:05:43,110 --> 00:05:44,900 and then creates a nice looking format. 105 00:05:47,700 --> 00:05:51,350 So let's go right underneath the set timer text, and see that one takes a string. 106 00:05:51,350 --> 00:05:53,090 Let's pick one that takes an integer. 107 00:05:59,720 --> 00:06:00,870 Then we'll say remainingSeconds. 108 00:06:03,670 --> 00:06:07,740 Okay, so all we gotta do is a little bit of math, right? 109 00:06:07,740 --> 00:06:09,940 So first let's determine what the minutes are. 110 00:06:09,940 --> 00:06:11,840 That's pretty easy, right? 111 00:06:11,840 --> 00:06:16,100 Remember the way you do that is we have remainingSeconds, and 112 00:06:16,100 --> 00:06:19,433 that's divided by 60, that'll get us the minutes. 113 00:06:19,433 --> 00:06:23,784 Remember in math those things called remainders after division happens, 114 00:06:23,784 --> 00:06:26,800 you know, like, 12 divided by 7 is 1, and there's a remainder of 5. 115 00:06:26,800 --> 00:06:32,320 Well, you can do that, and what that's known as in programming is a modulo. 116 00:06:32,320 --> 00:06:34,530 So you use the percent sign to do that. 117 00:06:34,530 --> 00:06:35,570 So let's go ahead and do that. 118 00:06:35,570 --> 00:06:39,782 So we say, int seconds = 119 00:06:39,782 --> 00:06:44,600 remainingSeconds % 60. 120 00:06:44,600 --> 00:06:47,608 So if you divide this by 60, what's remaining afterwards, 121 00:06:47,608 --> 00:06:48,810 is what that's saying. 122 00:06:51,260 --> 00:06:57,403 And then we'll say setTimerText, again calling the original method, 123 00:06:57,403 --> 00:07:04,670 and we'll use a String.format and we wanna make sure that there are leading zeroes. 124 00:07:04,670 --> 00:07:08,790 And the way that we do that is you say 0 and at least 2. 125 00:07:08,790 --> 00:07:12,260 And then you say decimal, right, so that's the %d. 126 00:07:12,260 --> 00:07:16,690 But if you put 02 in there, it will pad it 2 with zeros. 127 00:07:16,690 --> 00:07:21,750 And then let's do that again, %02d. 128 00:07:21,750 --> 00:07:27,110 And what will happen there is we can replace those with minutes, seconds. 129 00:07:30,100 --> 00:07:32,362 Right, makes sense? 130 00:07:32,362 --> 00:07:38,136 So, now we can call in our prepare attempt, 131 00:07:38,136 --> 00:07:47,670 we can call setTimerText = mCurrentAttempt.getRemainingSeconds. 132 00:07:51,060 --> 00:07:56,542 And if we start this off, we can remove the very dumb joke where we had a hammer, 133 00:07:56,542 --> 00:07:58,800 and let's just put 0 in there. 134 00:07:58,800 --> 00:08:00,150 And then let's see what happens when we run it. 135 00:08:02,360 --> 00:08:05,235 Perfect. So there's 0 turned into pretty string, 136 00:08:05,235 --> 00:08:06,120 00:00. 137 00:08:06,120 --> 00:08:07,150 Awesome. 138 00:08:08,770 --> 00:08:12,130 So now you know how to create properties that when changed 139 00:08:12,130 --> 00:08:14,820 send events out to all their listeners. 140 00:08:14,820 --> 00:08:19,030 You also learned how to bind a property in FXML to a controller. 141 00:08:19,030 --> 00:08:23,290 This is a really nice powerful pattern that JavaFX gives you out of the box. 142 00:08:24,740 --> 00:08:28,200 I've added links in the teacher's notes, and I highly suggest that you get more 143 00:08:28,200 --> 00:08:30,669 familiar with this powerful feature of your GUI framework. 144 00:08:32,260 --> 00:08:34,390 Nice refresher on method overloading. 145 00:08:34,390 --> 00:08:36,840 See how practical its use was there? 146 00:08:36,840 --> 00:08:40,810 We allow anyone to pass in a string or an integer and 147 00:08:40,810 --> 00:08:42,350 the timer text gets set properly. 148 00:08:43,360 --> 00:08:47,120 Remember to use that method overloading trick to help make what you offer 149 00:08:47,120 --> 00:08:48,870 very clear to consumers of your code. 150 00:08:50,440 --> 00:08:52,830 You also learned about the modulo operator, 151 00:08:52,830 --> 00:08:56,980 which is used to find the remainder of division between two numbers. 152 00:08:56,980 --> 00:08:58,870 For the remainder of this course, 153 00:08:58,870 --> 00:09:01,800 we're going to get this timer ticking, right after this exercise.