WEBVTT 1 00:00:02.460 --> 00:00:04.299 - [Instructor] So in the last few videos, we've produced 2 00:00:04.299 --> 00:00:08.428 a scrollable subclass of the tkinter Listbox class. 3 00:00:08.428 --> 00:00:12.568 We then populated the list from our music database. 4 00:00:12.568 --> 00:00:14.706 So we've got everything we need to move the database 5 00:00:14.706 --> 00:00:18.529 functionality into another subclass to produce a listbox 6 00:00:18.529 --> 00:00:22.919 that automatically displays data from a database table. 7 00:00:22.919 --> 00:00:25.667 But before we start, we have to decide how we're 8 00:00:25.667 --> 00:00:29.620 going to initialise the instances of our new class. 9 00:00:29.620 --> 00:00:31.128 Now, we're obviously going to have to tell it 10 00:00:31.128 --> 00:00:32.931 the name of the table that it should get 11 00:00:32.931 --> 00:00:36.510 the data from and which field it needs to display. 12 00:00:36.510 --> 00:00:40.007 So it's a good idea to provide a database connexion as well 13 00:00:40.007 --> 00:00:43.381 so that our classes don't have to rely on a global variable. 14 00:00:43.381 --> 00:00:45.734 A sort order would also be useful. 15 00:00:45.734 --> 00:00:47.794 The songs should be listed in track order, 16 00:00:47.794 --> 00:00:49.295 the order they appear on the album, 17 00:00:49.295 --> 00:00:51.640 but we're displaying the song titles. 18 00:00:51.640 --> 00:00:54.031 So sorting by the song title wouldn't be 19 00:00:54.031 --> 00:00:56.175 what users were expecting to see. 20 00:00:56.175 --> 00:00:59.197 Now, we can make the default sort order the displayed field 21 00:00:59.197 --> 00:01:02.524 so that if a different sort order isn't specified, 22 00:01:02.524 --> 00:01:05.861 the list will then sort the items alphabetically. 23 00:01:05.861 --> 00:01:07.362 Now, at the moment, when we run the programme, 24 00:01:07.362 --> 00:01:10.727 only one of our listboxes displays data to start with. 25 00:01:10.727 --> 00:01:12.579 So what we need is some way to trigger 26 00:01:12.579 --> 00:01:15.833 the initial load of data for those instances 27 00:01:15.833 --> 00:01:19.403 that will display data as soon as they're created. 28 00:01:19.403 --> 00:01:20.457 And we also need some way 29 00:01:20.457 --> 00:01:22.990 to get the other listboxes to load their data 30 00:01:22.990 --> 00:01:26.214 once we know the ID of the artist or album, 31 00:01:26.214 --> 00:01:28.747 and in fact it would make sense to use the same method 32 00:01:28.747 --> 00:01:32.232 in both cases and just pass none for the ID 33 00:01:32.232 --> 00:01:34.523 when we're loading the first lists. 34 00:01:34.523 --> 00:01:36.661 All right, so that's probably enough to start with. 35 00:01:36.661 --> 00:01:40.175 So let's go ahead now and create DataListbox class 36 00:01:40.175 --> 00:01:43.537 and I'm gonna add this after this Scrollbox class 37 00:01:43.537 --> 00:01:46.339 that we've created in the jukebox.py file. 38 00:01:46.339 --> 00:01:49.232 So I'm gonna add the customary two lines, 39 00:01:49.232 --> 00:01:51.652 two blank lines between classes here, 40 00:01:51.652 --> 00:01:55.402 and we're gonna start with class DataListBox, 41 00:01:58.610 --> 00:02:03.008 and in parentheses, it's going to be Scrollbox, colon, 42 00:02:03.008 --> 00:02:05.376 enter there, a space, and then we're going to define 43 00:02:05.376 --> 00:02:08.793 our init method, so def, space, __init__, 44 00:02:09.749 --> 00:02:11.674 and I'll just select that automatically. 45 00:02:11.674 --> 00:02:14.807 The first parameter in parentheses was added automatically, 46 00:02:14.807 --> 00:02:17.948 self, but we want these other arguments now, 47 00:02:17.948 --> 00:02:19.948 so comma, space, window, 48 00:02:22.819 --> 00:02:24.794 comma, space, connexion, 49 00:02:24.794 --> 00:02:26.593 comma, space, table, 50 00:02:26.593 --> 00:02:28.328 comma, space, field, 51 00:02:28.328 --> 00:02:30.328 comma, space, sort_order 52 00:02:31.541 --> 00:02:34.916 equals, and two parentheses, left and right. 53 00:02:34.916 --> 00:02:38.246 Then lastly, comma, space, and then star, star, 54 00:02:38.246 --> 00:02:39.829 K-W-args or kwargs. 55 00:02:42.152 --> 00:02:44.689 All right, and I'm just gonna put in, in a comment here, 56 00:02:44.689 --> 00:02:46.917 what the code would be for Python 2. 57 00:02:46.917 --> 00:02:51.084 Scrollbox.__init__(self, window, **kwargs), 58 00:02:58.538 --> 00:03:00.307 and something there for Python 2, 59 00:03:00.307 --> 00:03:02.523 just so if you're following along with Python 2, 60 00:03:02.523 --> 00:03:04.023 you'll know what to do there. 61 00:03:04.023 --> 00:03:06.425 All right, but in our case, we're going to do a super, 62 00:03:06.425 --> 00:03:10.342 parentheses, dot __init__, and we're gonna pass 63 00:03:11.923 --> 00:03:15.173 to this super call window and **kwargs. 64 00:03:19.115 --> 00:03:22.064 Next, we're going to do self.cursor is equal 65 00:03:22.064 --> 00:03:23.814 to connection.cursor, 66 00:03:25.385 --> 00:03:27.903 or call to the cursor method, to be more precise. 67 00:03:27.903 --> 00:03:31.536 We've got self.table is equal to table, 68 00:03:31.536 --> 00:03:34.947 and self.field is equal to field. 69 00:03:34.947 --> 00:03:36.198 Let's just move this up a little bit 70 00:03:36.198 --> 00:03:39.303 so we can see what we're doing here. 71 00:03:39.303 --> 00:03:43.470 And we wanna build a SQL query now, so self.sql_select 72 00:03:45.039 --> 00:03:49.327 is equal to SELECT in double quotes with a space, 73 00:03:49.327 --> 00:03:50.660 plus self.field, 74 00:03:52.160 --> 00:03:55.410 plus, double quotes, comma, space, _id, 75 00:03:57.930 --> 00:04:01.161 end of double quotes, plus another set of double quotes 76 00:04:01.161 --> 00:04:04.147 with the word FROM with a space around the word FROM 77 00:04:04.147 --> 00:04:08.314 plus self.table, and then we'll put if sort_order, 78 00:04:11.338 --> 00:04:15.421 colon, and then we'll do self.sql_select is equal 79 00:04:16.829 --> 00:04:19.751 to a space with double quotes with a space 80 00:04:19.751 --> 00:04:23.402 around the text, ORDER BY, that we're adding, 81 00:04:23.402 --> 00:04:25.735 plus, then in single quotes, 82 00:04:27.097 --> 00:04:30.514 comma, .join(sort_order) 83 00:04:33.073 --> 00:04:35.728 and then we'll put an else: otherwise for that. 84 00:04:35.728 --> 00:04:40.504 It's going to be self.sql_select equals ORDER BY 85 00:04:40.504 --> 00:04:45.008 in double quotes with a space around both terms, 86 00:04:45.008 --> 00:04:46.414 at the start and end, in other words, 87 00:04:46.414 --> 00:04:47.497 plus self_... 88 00:04:48.997 --> 00:04:51.009 Sorry, self.field. 89 00:04:51.009 --> 00:04:53.172 I'm gonna put another line there to keep Python happy 90 00:04:53.172 --> 00:04:57.458 with the method, the function that we've got below that. 91 00:04:57.458 --> 00:05:00.590 All right, so starting off here, out init method is calling 92 00:05:00.590 --> 00:05:04.340 the super method for Scrollbox, and I've included 93 00:05:04.340 --> 00:05:07.804 the Python 2 syntax on line 29 as well for that. 94 00:05:07.804 --> 00:05:09.984 So next, we create data attributes 95 00:05:09.984 --> 00:05:12.987 from the parameters passed to the init method. 96 00:05:12.987 --> 00:05:14.401 Now, we're going to work with a cursor 97 00:05:14.401 --> 00:05:16.196 so we store that rather than the connexions. 98 00:05:16.196 --> 00:05:19.171 You can see here, we're storing the actual cursor 99 00:05:19.171 --> 00:05:21.686 and not the connexion on line 32. 100 00:05:21.686 --> 00:05:24.218 Now, you should write a class to accept a cursor 101 00:05:24.218 --> 00:05:27.384 rather than a connexion, but it's probably more useful 102 00:05:27.384 --> 00:05:29.105 to provide a connexion. 103 00:05:29.105 --> 00:05:31.612 Now, I call it the column parameter field 104 00:05:31.612 --> 00:05:36.315 because we're working in the grid layout_manager down here, 105 00:05:36.315 --> 00:05:38.651 and column could then get confusing for that reason. 106 00:05:38.651 --> 00:05:40.555 And table of course is the table 107 00:05:40.555 --> 00:05:42.845 that we're going to be selecting the data from. 108 00:05:42.845 --> 00:05:44.867 Now, the sort_order argument here, we have to find that 109 00:05:44.867 --> 00:05:46.789 as a tuple to allow the caller 110 00:05:46.789 --> 00:05:49.905 to specify multiple columns to sort on if they need to. 111 00:05:49.905 --> 00:05:52.472 Now, this doesn't make a lot of sense with our tables, 112 00:05:52.472 --> 00:05:54.327 but if we use the view, for example, 113 00:05:54.327 --> 00:05:57.126 from the previous videos, then it could get useful. 114 00:05:57.126 --> 00:05:59.466 And we're also trying to make the classes as general 115 00:05:59.466 --> 00:06:02.229 as possible so they can't be used in other programmes that 116 00:06:02.229 --> 00:06:07.131 perhaps have got more complicated database schemes in place. 117 00:06:07.131 --> 00:06:09.831 So the sql_select attribute's pretty straightforward, 118 00:06:09.831 --> 00:06:12.603 if you're reading that from line 36. 119 00:06:12.603 --> 00:06:14.405 Just contains a basic select statement 120 00:06:14.405 --> 00:06:17.239 to retrieve the required field and the row ID. 121 00:06:17.239 --> 00:06:19.344 Now, we're putting a restriction on the database 122 00:06:19.344 --> 00:06:21.123 that our class will work with. 123 00:06:21.123 --> 00:06:24.220 The table must have a column called _id. 124 00:06:24.220 --> 00:06:27.480 You can see that in here on line 36, and that's of course 125 00:06:27.480 --> 00:06:30.206 used to uniquely identify each row on the table. 126 00:06:30.206 --> 00:06:33.098 And actually that's not unusual, but if you wanted 127 00:06:33.098 --> 00:06:35.419 to remove that restriction, then you could request 128 00:06:35.419 --> 00:06:37.817 a primary key field as another parameter. 129 00:06:37.817 --> 00:06:39.462 We will not be doing that here. 130 00:06:39.462 --> 00:06:41.013 Now I've actually made a change here, 131 00:06:41.013 --> 00:06:43.254 so what I'm going to do is that's gonna be 132 00:06:43.254 --> 00:06:47.421 if sort_order, that actually should have been if sql_sort... 133 00:06:49.374 --> 00:06:50.420 I'm confusing myself here. 134 00:06:50.420 --> 00:06:52.886 Sql_sort for that as well. 135 00:06:52.886 --> 00:06:55.855 So what I was trying to do there is specify a SQL sort 136 00:06:55.855 --> 00:06:59.625 attribute with an order by clause, and we're catering for 137 00:06:59.625 --> 00:07:03.698 the fact that they may be passing that sort_order or not, 138 00:07:03.698 --> 00:07:06.427 so we're going to default to the field and order by that 139 00:07:06.427 --> 00:07:10.525 if I don't pass a parameter with the requested sort_order. 140 00:07:10.525 --> 00:07:12.082 Now, you could leave the default blank 141 00:07:12.082 --> 00:07:13.931 so that the data isn't sorted at all. 142 00:07:13.931 --> 00:07:15.554 That's the sort of detail you decide 143 00:07:15.554 --> 00:07:16.888 when designing your classes, 144 00:07:16.888 --> 00:07:20.341 and as long as the users are aware of how it works, 145 00:07:20.341 --> 00:07:21.775 then that would be fine. 146 00:07:21.775 --> 00:07:24.185 Now, I'm not including doc strings in the classes, 147 00:07:24.185 --> 00:07:26.040 because that would make the videos too long, 148 00:07:26.040 --> 00:07:28.314 but that would certainly be something you should add, 149 00:07:28.314 --> 00:07:29.937 especially when creating classes 150 00:07:29.937 --> 00:07:32.265 that should tend to be reused. 151 00:07:32.265 --> 00:07:34.684 All right, and again, in the case of a sort_order 152 00:07:34.684 --> 00:07:37.243 being passed, we're using .join with the sort_order 153 00:07:37.243 --> 00:07:39.634 and separating them by commas as is required 154 00:07:39.634 --> 00:07:43.444 to fulfil the syntax for an order by clause of SQL. 155 00:07:43.444 --> 00:07:46.653 All right, so the class at the moment doesn't load any data, 156 00:07:46.653 --> 00:07:50.013 so we need to implement the requery method 157 00:07:50.013 --> 00:07:51.938 that it's going to need. 158 00:07:51.938 --> 00:07:54.798 Now, if we're going to allow the listboxes to be requeried 159 00:07:54.798 --> 00:07:57.323 so that they can show new data, we need some way 160 00:07:57.323 --> 00:08:00.370 to clear the existing data out, so for that reason, 161 00:08:00.370 --> 00:08:02.202 we're also gonna add a clear method. 162 00:08:02.202 --> 00:08:04.869 So let's go ahead and add those. 163 00:08:06.201 --> 00:08:07.944 So we'll start with the clear method. 164 00:08:07.944 --> 00:08:11.142 So def clear, and of course self 165 00:08:11.142 --> 00:08:14.516 is the default parameter there, argument. 166 00:08:14.516 --> 00:08:16.849 Then we'll do a self.delete, 167 00:08:18.047 --> 00:08:20.448 in parentheses, zero, comma, space, 168 00:08:20.448 --> 00:08:24.615 tkinter.END, uppercase letters, and right parenthesis. 169 00:08:28.131 --> 00:08:31.684 And the next one we want is the requery method 170 00:08:31.684 --> 00:08:35.184 that we just talked about, so def requery, 171 00:08:36.984 --> 00:08:41.149 and argument is self again, automatically added by IntelliJ. 172 00:08:41.149 --> 00:08:43.232 Then we're going to print 173 00:08:44.375 --> 00:08:48.542 (self.sql_select + self.sql_sort) 174 00:08:50.183 --> 00:08:51.626 for debugging purposes. 175 00:08:51.626 --> 00:08:52.459 But what we're going to do 176 00:08:52.459 --> 00:08:54.959 is put a TODO delete this line 177 00:08:56.982 --> 00:08:59.138 so we know to come back later 178 00:08:59.138 --> 00:09:02.030 once the testing is complete and remove that. 179 00:09:02.030 --> 00:09:04.172 And in terms of what we're going to do now 180 00:09:04.172 --> 00:09:08.339 is from our requerying, we first clear the listbox contents 181 00:09:09.292 --> 00:09:10.857 before re-loading, which would make sense 182 00:09:10.857 --> 00:09:13.037 so we haven't got duplicate entries. 183 00:09:13.037 --> 00:09:16.709 So we do a self.clear to call our clear method 184 00:09:16.709 --> 00:09:19.149 that we just defined on line 43, 185 00:09:19.149 --> 00:09:22.232 and I just remove one of those lines. 186 00:09:23.105 --> 00:09:25.276 And after self.clear, 187 00:09:25.276 --> 00:09:30.001 then we're gonna put for value in self.cursor... 188 00:09:30.001 --> 00:09:32.918 Oops, that should have been cursor. 189 00:09:33.777 --> 00:09:36.908 Then we wanna do self.insert, 190 00:09:36.908 --> 00:09:40.087 and the argument is gonna be tkinter.END, 191 00:09:40.087 --> 00:09:41.754 comma, space, value, 192 00:09:42.852 --> 00:09:46.254 and the value zero in square brackets, 193 00:09:46.254 --> 00:09:48.254 then end of parentheses. 194 00:09:50.924 --> 00:09:54.084 So the clear method, as you can see on line 42, 195 00:09:54.084 --> 00:09:57.682 and the code's on line 43, that uses the listbox delete 196 00:09:57.682 --> 00:10:00.993 method and we're specifying the entire range of values, 197 00:10:00.993 --> 00:10:04.118 going from zero to tkinter.n constant, 198 00:10:04.118 --> 00:10:07.054 and that constant represents the last item in the list. 199 00:10:07.054 --> 00:10:08.563 So consequently, calling that 200 00:10:08.563 --> 00:10:10.695 will actually delete all the entries. 201 00:10:10.695 --> 00:10:13.856 Now, the requery method that we've defined on line 45, 202 00:10:13.856 --> 00:10:16.129 that's where our SQL statement's built up, 203 00:10:16.129 --> 00:10:20.767 from the sql_select part as well as the sql_sort part. 204 00:10:20.767 --> 00:10:22.474 So I've printed that out, but the other thing we need 205 00:10:22.474 --> 00:10:25.569 to do is actually add that, so I'm talking about how it's 206 00:10:25.569 --> 00:10:27.173 being added, but we haven't actually done that yet, 207 00:10:27.173 --> 00:10:30.256 so it's gonna be self.cursor.execute, 208 00:10:33.060 --> 00:10:37.227 and it's gonna be self.sql_select + self.sql_sort. 209 00:10:39.640 --> 00:10:42.118 So obviously we're printing it out on line 46. 210 00:10:42.118 --> 00:10:45.378 Line 47, we're actually executing the combination 211 00:10:45.378 --> 00:10:49.715 of the sql_select that we've generated on line 36 up here, 212 00:10:49.715 --> 00:10:52.631 then the sql_sort that we're creating 213 00:10:52.631 --> 00:10:55.662 on either line 38 or line 40, depending on whether 214 00:10:55.662 --> 00:10:59.112 that argument's been passed for the sort_order. 215 00:10:59.112 --> 00:11:02.650 So then we're executing the SQL code, as I said, on line 47. 216 00:11:02.650 --> 00:11:03.483 All right, once we've done that, 217 00:11:03.483 --> 00:11:05.694 the rest of this code should look pretty familiar. 218 00:11:05.694 --> 00:11:06.953 We're executing the query 219 00:11:06.953 --> 00:11:10.025 and looping over the cursor as you can see here. 220 00:11:10.025 --> 00:11:12.545 We're executing the query here on line 47. 221 00:11:12.545 --> 00:11:14.444 We're clearing the listbox contents 222 00:11:14.444 --> 00:11:17.449 and then we're looping through the values one by one 223 00:11:17.449 --> 00:11:20.052 and then actually adding each one to the listbox. 224 00:11:20.052 --> 00:11:22.624 And just a note here, on line 52, 225 00:11:22.624 --> 00:11:25.736 remember that we get a tuple representing each row. 226 00:11:25.736 --> 00:11:28.228 Now as our query specified the column we want 227 00:11:28.228 --> 00:11:31.339 and the ID, we add the first item from the tuple 228 00:11:31.339 --> 00:11:34.022 into the list and that's why we use the value zero 229 00:11:34.022 --> 00:11:37.679 in the square brackets to indicate that first value. 230 00:11:37.679 --> 00:11:39.855 So at that point, that should actually work. 231 00:11:39.855 --> 00:11:41.779 So we should be able to test this class now 232 00:11:41.779 --> 00:11:45.750 before the video ends, so let's remove all the code 233 00:11:45.750 --> 00:11:49.848 to populate the lists from the artist listbox 234 00:11:49.848 --> 00:11:52.946 and replace it with a call to this requery method 235 00:11:52.946 --> 00:11:55.465 just to check that and see that it'll actually work. 236 00:11:55.465 --> 00:11:58.363 So to do that, we'll come down here, 237 00:11:58.363 --> 00:12:02.530 down to the setup here for Artists Listbox on line 101. 238 00:12:04.306 --> 00:12:06.292 And what we wanna do first is we wanna change 239 00:12:06.292 --> 00:12:09.046 the definition, so we wanna change Scrollbox now 240 00:12:09.046 --> 00:12:10.732 to use our new class we've created, 241 00:12:10.732 --> 00:12:13.949 so that's going to be DataListBox, and next, 242 00:12:13.949 --> 00:12:17.282 we're going to remove the SQL code here. 243 00:12:18.948 --> 00:12:20.271 And instead, we're going to replace that 244 00:12:20.271 --> 00:12:23.104 with a call to artistList.requery. 245 00:12:24.864 --> 00:12:25.857 We're just gonna be calling the code 246 00:12:25.857 --> 00:12:27.422 that we've just written. 247 00:12:27.422 --> 00:12:31.422 So let's check that first to make sure it works. 248 00:12:34.043 --> 00:12:35.721 And we've got an error, and of course the reason is 249 00:12:35.721 --> 00:12:37.788 we haven't specified our other parameters. 250 00:12:37.788 --> 00:12:39.028 We need to go ahead and do that. 251 00:12:39.028 --> 00:12:41.236 So we've got at the moment, we've got DataListBox, 252 00:12:41.236 --> 00:12:44.872 we've got mainWindow, but we also need a connexion, 253 00:12:44.872 --> 00:12:47.240 we need a table name, and we also need 254 00:12:47.240 --> 00:12:49.974 the column that we want to be displaying. 255 00:12:49.974 --> 00:12:51.514 So, we'll add those. 256 00:12:51.514 --> 00:12:54.480 So comma, space, conn, for the connexion. 257 00:12:54.480 --> 00:12:58.767 Comma, space, artists in double quote, being the table name, 258 00:12:58.767 --> 00:13:00.684 and comma, space, name, 259 00:13:01.883 --> 00:13:03.943 being the actual field or column. 260 00:13:03.943 --> 00:13:06.442 And there's another option there for sort_order, 261 00:13:06.442 --> 00:13:07.963 but we're not going to add that yet. 262 00:13:07.963 --> 00:13:09.643 We can add that option in later, 263 00:13:09.643 --> 00:13:11.883 just to see that it does work. 264 00:13:11.883 --> 00:13:15.716 Let's go ahead and do that and run that again. 265 00:13:17.036 --> 00:13:20.115 This time, you can see we've got the SQL printing out, 266 00:13:20.115 --> 00:13:22.098 and if we go back and have a look at our code, 267 00:13:22.098 --> 00:13:24.388 we can see that we have got our artists populated, 268 00:13:24.388 --> 00:13:27.010 so it is working now, which is fantastic. 269 00:13:27.010 --> 00:13:28.300 All right, so let's continue on now. 270 00:13:28.300 --> 00:13:29.633 Close that down. 271 00:13:30.992 --> 00:13:32.234 All right, so now that we've done that, 272 00:13:32.234 --> 00:13:34.864 we should be able to replace the other two calls 273 00:13:34.864 --> 00:13:37.614 to our albums and also our songs. 274 00:13:39.496 --> 00:13:41.023 So we wanna change albumList here 275 00:13:41.023 --> 00:13:42.738 where it's just calling Scrollbox. 276 00:13:42.738 --> 00:13:46.630 We wanna change that now to call our DataListBox 277 00:13:46.630 --> 00:13:49.932 and the arguments are going to be mainWindow again, 278 00:13:49.932 --> 00:13:53.198 conn for our connexion, comma, space, this time it's 279 00:13:53.198 --> 00:13:55.911 going to be albums for the table name, comma, space, 280 00:13:55.911 --> 00:13:59.637 name for the field/column name, 281 00:13:59.637 --> 00:14:02.603 comma, space, this time we'll add a sort_order, 282 00:14:02.603 --> 00:14:05.686 so I'm going to do sort_order equals, 283 00:14:06.767 --> 00:14:10.150 and I want parentheses, and within the parentheses, 284 00:14:10.150 --> 00:14:14.053 we want name in double quotes and a comma, 285 00:14:14.053 --> 00:14:16.831 and we add a second parenthesis there. 286 00:14:16.831 --> 00:14:19.924 Okay, like so, and we'll delete that line there. 287 00:14:19.924 --> 00:14:21.060 Last entry. 288 00:14:21.060 --> 00:14:23.558 Then what we need to do on the line immediately after that, 289 00:14:23.558 --> 00:14:27.725 we wanna put albumList.requery, and we leave the grid 290 00:14:29.023 --> 00:14:30.543 and the configures there were before, 291 00:14:30.543 --> 00:14:34.151 and we also leave the binding as it was before. 292 00:14:34.151 --> 00:14:38.306 And lastly, for songList, we've got the Scrollbox code here. 293 00:14:38.306 --> 00:14:41.624 We'll change that also to be DataListBox, 294 00:14:41.624 --> 00:14:46.546 and the arguments for that will be mainWindow, conn again, 295 00:14:46.546 --> 00:14:50.458 and for the table, it's going to be songs, comma, space, 296 00:14:50.458 --> 00:14:52.916 title is going to be the name of the field, 297 00:14:52.916 --> 00:14:57.449 and let's also specify a sort_order for this one, 298 00:14:57.449 --> 00:15:01.756 and we can just specify that as track and title 299 00:15:01.756 --> 00:15:05.698 in parentheses, double quotes, separated by a comma, 300 00:15:05.698 --> 00:15:07.706 and finish off the right parenthesis. 301 00:15:07.706 --> 00:15:09.857 And then of course on the next line, 302 00:15:09.857 --> 00:15:13.607 we need to do a requery, so songList.requery. 303 00:15:16.901 --> 00:15:20.075 All right, so let's actually try running this. 304 00:15:20.075 --> 00:15:22.271 You can see the three sets of SQL that have been executed 305 00:15:22.271 --> 00:15:25.820 there for artists, albums, and songs, and incidentally, 306 00:15:25.820 --> 00:15:28.445 there's no good reason for sorting the songList 307 00:15:28.445 --> 00:15:31.987 on both track and title, really other than to prove 308 00:15:31.987 --> 00:15:34.525 that the code doesn't crash and so that we can check 309 00:15:34.525 --> 00:15:36.025 the SQL statement that we're printing out, 310 00:15:36.025 --> 00:15:39.207 and you can see there's multiple sort_orders quite happily 311 00:15:39.207 --> 00:15:42.201 separated both with a comma and made that valid code. 312 00:15:42.201 --> 00:15:44.887 But importantly, let's just actually check this works. 313 00:15:44.887 --> 00:15:47.549 And you can see that we've got it all working nicely. 314 00:15:47.549 --> 00:15:49.421 And now all three Listboxes at this point 315 00:15:49.421 --> 00:15:51.606 are now showing data, which is what we wanted, 316 00:15:51.606 --> 00:15:54.461 and again, the SQL output that we've got over here, 317 00:15:54.461 --> 00:15:57.415 I'll just move this over, looks fine as well. 318 00:15:57.415 --> 00:15:59.146 So that's actually pretty cool. 319 00:15:59.146 --> 00:16:02.484 With subclass of tkinter.listbox to reduce our scrollable 320 00:16:02.484 --> 00:16:05.683 listbox, and just to confirm, we have got scrolling enabled 321 00:16:05.683 --> 00:16:10.433 for all three listboxes there, so that's working nicely, 322 00:16:10.433 --> 00:16:12.108 and we can now load that data 323 00:16:12.108 --> 00:16:13.779 from a database table as you can see. 324 00:16:13.779 --> 00:16:15.160 Working pretty well. 325 00:16:15.160 --> 00:16:16.995 But we're still not done at this point, 326 00:16:16.995 --> 00:16:18.497 and in the next video, we're going to add the code 327 00:16:18.497 --> 00:16:21.354 to allow our DataListboxes to be linked together. 328 00:16:21.354 --> 00:16:23.984 Then, when we select an item in one list, the related 329 00:16:23.984 --> 00:16:26.420 data will show in another like it was doing earlier 330 00:16:26.420 --> 00:16:29.359 before we made the change to move over to the DataListbox. 331 00:16:29.359 --> 00:16:32.409 But let's work on that in the next video.