1 00:00:00,480 --> 00:00:03,480 foreign 2 00:00:08,780 --> 00:00:13,559 like to introduce Russell Keith McGee 3 00:00:11,460 --> 00:00:16,560 Russell is a 4 00:00:13,559 --> 00:00:19,260 um is an important contributor 5 00:00:16,560 --> 00:00:22,380 in many ways to to Python and the python 6 00:00:19,260 --> 00:00:24,240 sort of ecosystem and Community Russell 7 00:00:22,380 --> 00:00:25,619 is a fellow of the Python software 8 00:00:24,240 --> 00:00:28,019 Foundation 9 00:00:25,619 --> 00:00:30,480 um has has been very involved in the 10 00:00:28,019 --> 00:00:31,500 Django project and is the author of The 11 00:00:30,480 --> 00:00:34,140 beware 12 00:00:31,500 --> 00:00:36,719 Suite of the sort of original author of 13 00:00:34,140 --> 00:00:37,860 The beware Suite which is now growing 14 00:00:36,719 --> 00:00:40,020 and uh 15 00:00:37,860 --> 00:00:42,540 um so Russell's going to talk about the 16 00:00:40,020 --> 00:00:44,640 beware suite and uh in particular about 17 00:00:42,540 --> 00:00:46,620 cross-platform user interfaces so please 18 00:00:44,640 --> 00:00:48,840 give a warm welcome to Russell Keith 19 00:00:46,620 --> 00:00:51,840 McGee 20 00:00:48,840 --> 00:00:51,840 foreign 21 00:00:53,539 --> 00:00:57,480 as he said my name is Russell Keith 22 00:00:55,739 --> 00:01:00,000 McGee and today I'm going to show you 23 00:00:57,480 --> 00:01:02,239 how to build a cross-platform GUI with 24 00:01:00,000 --> 00:01:04,080 python a little bit about me I am from 25 00:01:02,239 --> 00:01:06,540 otherwise known as Perth Western 26 00:01:04,080 --> 00:01:09,060 Australia I am a principal engineer in 27 00:01:06,540 --> 00:01:11,520 the open source group at Anaconda not 28 00:01:09,060 --> 00:01:13,979 the camping store the data science and 29 00:01:11,520 --> 00:01:15,479 python people Anaconda pays me to attend 30 00:01:13,979 --> 00:01:17,100 conferences like this one to talk to 31 00:01:15,479 --> 00:01:18,840 people like you so I'd like to thank 32 00:01:17,100 --> 00:01:20,820 them for that support they also support 33 00:01:18,840 --> 00:01:22,380 the python open source ecosystem more 34 00:01:20,820 --> 00:01:24,600 broadly by providing direct financial 35 00:01:22,380 --> 00:01:26,580 support to organizations like num focus 36 00:01:24,600 --> 00:01:28,380 and by employing developers to work 37 00:01:26,580 --> 00:01:30,900 full-time on open source projects 38 00:01:28,380 --> 00:01:32,340 projects like Jupiter number and the 39 00:01:30,900 --> 00:01:34,799 open source project that I founded 40 00:01:32,340 --> 00:01:36,840 beware for those who haven't come across 41 00:01:34,799 --> 00:01:39,119 it before beware is not a single product 42 00:01:36,840 --> 00:01:40,500 or library or tool it is a collection of 43 00:01:39,119 --> 00:01:42,360 Open Source tools and libraries for 44 00:01:40,500 --> 00:01:45,420 creating native user interfaces in 45 00:01:42,360 --> 00:01:47,939 Python for desktop but also for iOS for 46 00:01:45,420 --> 00:01:51,420 Android for single page web apps and in 47 00:01:47,939 --> 00:01:53,100 Alpha form for console apps uh in every 48 00:01:51,420 --> 00:01:55,020 tool in the suite solves one very 49 00:01:53,100 --> 00:01:57,119 specific part of the overall problem of 50 00:01:55,020 --> 00:01:58,979 writing a GUI app in Python and 51 00:01:57,119 --> 00:02:01,320 distributing that app to other people on 52 00:01:58,979 --> 00:02:02,939 various platforms Anaconda supports 53 00:02:01,320 --> 00:02:04,200 beware to ensure that python remains a 54 00:02:02,939 --> 00:02:05,759 viable programming language on the 55 00:02:04,200 --> 00:02:07,439 platforms that people are increasingly 56 00:02:05,759 --> 00:02:09,479 using as part of their day-to-day 57 00:02:07,439 --> 00:02:11,580 Computing life phones tablets and so on 58 00:02:09,479 --> 00:02:14,160 however it is important to note that 59 00:02:11,580 --> 00:02:16,020 beware is not an anaconda product or 60 00:02:14,160 --> 00:02:17,520 anything like that it is a fully open 61 00:02:16,020 --> 00:02:19,379 source project with independent 62 00:02:17,520 --> 00:02:21,660 governance and funding I just happen to 63 00:02:19,379 --> 00:02:22,920 be paid by Anaconda to work on it full 64 00:02:21,660 --> 00:02:25,620 time 65 00:02:22,920 --> 00:02:28,260 one of the components of Beware is toga 66 00:02:25,620 --> 00:02:31,980 a cross-platform GUI toolkit this talk 67 00:02:28,260 --> 00:02:34,379 is not a toga talk at least not directly 68 00:02:31,980 --> 00:02:36,120 the Practical examples are going to lean 69 00:02:34,379 --> 00:02:38,580 toga but that's just because I've got to 70 00:02:36,120 --> 00:02:40,379 show something however the ideas and 71 00:02:38,580 --> 00:02:42,000 problems I'm going to be discussing are 72 00:02:40,379 --> 00:02:44,220 very generic you will see the same 73 00:02:42,000 --> 00:02:46,019 problems and broadly speaking the same 74 00:02:44,220 --> 00:02:49,200 Solutions just with different spelling 75 00:02:46,019 --> 00:02:51,720 no matter which GUI toolkit you use 76 00:02:49,200 --> 00:02:54,060 but before we start building our GUI app 77 00:02:51,720 --> 00:02:56,580 first thing we have to ask do you need a 78 00:02:54,060 --> 00:02:57,959 GUI at all in many cases the answer is 79 00:02:56,580 --> 00:02:59,640 no you do not 80 00:02:57,959 --> 00:03:01,680 you know the adage this meeting should 81 00:02:59,640 --> 00:03:03,239 have been an email this app should have 82 00:03:01,680 --> 00:03:05,340 been a mailing list 83 00:03:03,239 --> 00:03:07,860 as software professionals we owe it to 84 00:03:05,340 --> 00:03:10,200 our clients to interrogate why they want 85 00:03:07,860 --> 00:03:11,580 an app do they actually have a use case 86 00:03:10,200 --> 00:03:12,840 that requires an app or does an 87 00:03:11,580 --> 00:03:14,580 executive just want to be able to say 88 00:03:12,840 --> 00:03:17,340 we've got an app 89 00:03:14,580 --> 00:03:19,379 this is on us as developers to push back 90 00:03:17,340 --> 00:03:21,720 against clients that ask for things to 91 00:03:19,379 --> 00:03:23,340 interrogate why a client wants an app 92 00:03:21,720 --> 00:03:24,780 and if their use case doesn't actually 93 00:03:23,340 --> 00:03:26,700 add up convince them that their 94 00:03:24,780 --> 00:03:29,760 development time is better spent 95 00:03:26,700 --> 00:03:31,739 elsewhere sometimes our website is the 96 00:03:29,760 --> 00:03:33,060 right answer to a problem especially if 97 00:03:31,739 --> 00:03:34,379 you're able to take the effort that you 98 00:03:33,060 --> 00:03:36,300 would have spilled would have spent 99 00:03:34,379 --> 00:03:38,099 trying to build an app and direct that 100 00:03:36,300 --> 00:03:39,060 towards improving the web user 101 00:03:38,099 --> 00:03:41,040 experience 102 00:03:39,060 --> 00:03:42,780 for example websites do have distinct 103 00:03:41,040 --> 00:03:45,180 advantages over apps features like deep 104 00:03:42,780 --> 00:03:47,640 linking are in the blood of how websites 105 00:03:45,180 --> 00:03:49,099 work you can deep link into an app but 106 00:03:47,640 --> 00:03:51,360 it isn't immediately discoverable 107 00:03:49,099 --> 00:03:53,040 websites are single deployments where a 108 00:03:51,360 --> 00:03:55,019 deployment has immediate and Universal 109 00:03:53,040 --> 00:03:56,459 effect if you find a bug in a website 110 00:03:55,019 --> 00:03:58,379 and you need to deploy a fix urgently 111 00:03:56,459 --> 00:04:00,420 you can push an update and everyone has 112 00:03:58,379 --> 00:04:02,099 that update pretty much immediately that 113 00:04:00,420 --> 00:04:04,739 is effectively impossible to do with an 114 00:04:02,099 --> 00:04:06,180 app and apps especially mobile apps are 115 00:04:04,739 --> 00:04:07,920 distributed through the wall Gardens of 116 00:04:06,180 --> 00:04:10,379 app stores your ability to play in that 117 00:04:07,920 --> 00:04:12,360 Garden is 100 at the whim and mercy at 118 00:04:10,379 --> 00:04:13,739 the owners of those Gardens if an app 119 00:04:12,360 --> 00:04:15,720 store rejects your app or doesn't 120 00:04:13,739 --> 00:04:17,639 approve it in a timely fashion you are 121 00:04:15,720 --> 00:04:19,019 pretty much out of luck and then there's 122 00:04:17,639 --> 00:04:20,760 the mandatory profit sharing that app 123 00:04:19,019 --> 00:04:23,160 stores in force 124 00:04:20,760 --> 00:04:25,560 so when is an app the right solution 125 00:04:23,160 --> 00:04:27,720 well native apps allow you to work with 126 00:04:25,560 --> 00:04:29,820 local data if your data files are 127 00:04:27,720 --> 00:04:32,160 multiple gigabytes uploading to a web 128 00:04:29,820 --> 00:04:34,979 app probably isn't a viable option if 129 00:04:32,160 --> 00:04:37,139 the data is sensitive for any reason you 130 00:04:34,979 --> 00:04:39,120 need to be very careful about where you 131 00:04:37,139 --> 00:04:40,320 are uploading your data local data 132 00:04:39,120 --> 00:04:42,660 storage and manipulation may be 133 00:04:40,320 --> 00:04:43,680 preferable or even required in those 134 00:04:42,660 --> 00:04:45,780 cases 135 00:04:43,680 --> 00:04:47,220 remember your attack surface is only 136 00:04:45,780 --> 00:04:49,620 ever as big as the data that you 137 00:04:47,220 --> 00:04:51,300 actually hold you can't leak data that 138 00:04:49,620 --> 00:04:52,440 never left the user's device in the 139 00:04:51,300 --> 00:04:54,419 first place 140 00:04:52,440 --> 00:04:56,220 local data also matters if users are 141 00:04:54,419 --> 00:04:58,139 going to be working offline Outback 142 00:04:56,220 --> 00:04:59,880 locations have bad to non-existent 143 00:04:58,139 --> 00:05:01,919 mobile data coverage and unless you've 144 00:04:59,880 --> 00:05:03,840 got access to a satellite some inner 145 00:05:01,919 --> 00:05:05,759 city locations have bad coverage on some 146 00:05:03,840 --> 00:05:09,000 mobile networks if I can't get a mobile 147 00:05:05,759 --> 00:05:11,699 data signal I can't use a web app but I 148 00:05:09,000 --> 00:05:13,500 can still use native apps on my phone 149 00:05:11,699 --> 00:05:15,300 native apps also allow you as a 150 00:05:13,500 --> 00:05:16,800 developer to deeply integrate the user 151 00:05:15,300 --> 00:05:18,600 experience or with the user experience 152 00:05:16,800 --> 00:05:20,400 of the device integration with task 153 00:05:18,600 --> 00:05:22,440 managers notifications taskbars 154 00:05:20,400 --> 00:05:24,780 application lifecycle and more these 155 00:05:22,440 --> 00:05:26,280 Integrations are difficult or impossible 156 00:05:24,780 --> 00:05:28,080 to do in a web context because the 157 00:05:26,280 --> 00:05:30,479 entire web experience is delivered 158 00:05:28,080 --> 00:05:33,000 through a the lens of a browser tab 159 00:05:30,479 --> 00:05:34,919 native apps have almost unlimited access 160 00:05:33,000 --> 00:05:37,080 to device Hardware things like cameras 161 00:05:34,919 --> 00:05:39,240 and peripheral ports and GPS readers web 162 00:05:37,080 --> 00:05:41,039 apis for these exist and they are 163 00:05:39,240 --> 00:05:42,900 getting better but they're also heavily 164 00:05:41,039 --> 00:05:44,580 sandboxed by the browser native apps 165 00:05:42,900 --> 00:05:46,740 have much lower level access to those 166 00:05:44,580 --> 00:05:50,100 services and when I say device Hardware 167 00:05:46,740 --> 00:05:52,139 this includes the CPU and GPU you can do 168 00:05:50,100 --> 00:05:54,060 some very impressive things with 169 00:05:52,139 --> 00:05:55,320 webassembly and related Technologies but 170 00:05:54,060 --> 00:05:57,360 if you need to do some computational 171 00:05:55,320 --> 00:05:59,160 heavy lifting a native app is going to 172 00:05:57,360 --> 00:06:01,560 give you much better results because you 173 00:05:59,160 --> 00:06:03,060 have direct access to multi-core CPU and 174 00:06:01,560 --> 00:06:05,820 GPU acceleration 175 00:06:03,060 --> 00:06:08,039 now some of these properties can be true 176 00:06:05,820 --> 00:06:09,660 of some web apps but when compared to a 177 00:06:08,039 --> 00:06:12,240 vanilla website these are areas where 178 00:06:09,660 --> 00:06:15,660 having a native app will be an advantage 179 00:06:12,240 --> 00:06:17,220 okay so you've decided your a GUI app is 180 00:06:15,660 --> 00:06:18,419 appropriate for your use case you know 181 00:06:17,220 --> 00:06:20,699 you want to use Python because why 182 00:06:18,419 --> 00:06:22,440 wouldn't you so how do you build your 183 00:06:20,699 --> 00:06:24,300 app well if you want to build a GUI app 184 00:06:22,440 --> 00:06:25,919 you need a GUI toolkit a GUI toolkit is 185 00:06:24,300 --> 00:06:27,479 the API that lets you put buttons and 186 00:06:25,919 --> 00:06:29,340 text inputs on the screen so your end 187 00:06:27,479 --> 00:06:30,539 user can interact with them the good 188 00:06:29,340 --> 00:06:32,759 news is that there's a whole lot of 189 00:06:30,539 --> 00:06:34,139 options for GUI toolkits in Python the 190 00:06:32,759 --> 00:06:36,900 bad news is that there's a whole lot of 191 00:06:34,139 --> 00:06:38,639 options for GUI toolkits in Python the 192 00:06:36,900 --> 00:06:40,620 python standard library has a GUI 193 00:06:38,639 --> 00:06:43,139 toolkit baked in called TK enter TK 194 00:06:40,620 --> 00:06:45,780 enter is tickle TK wrapped in Python now 195 00:06:43,139 --> 00:06:47,699 ten years ago I stood on the pycon 196 00:06:45,780 --> 00:06:49,440 Australia stage and gave an impassioned 197 00:06:47,699 --> 00:06:52,380 defense of TK inter 198 00:06:49,440 --> 00:06:54,840 I now run my own GUI Project Read into 199 00:06:52,380 --> 00:06:57,479 that what you will 200 00:06:54,840 --> 00:06:59,220 QT is the big name in cross-platform GUI 201 00:06:57,479 --> 00:07:01,139 space not just in Python it's the GUI 202 00:06:59,220 --> 00:07:02,639 toolkit used by KDE on Linux but it's 203 00:07:01,139 --> 00:07:04,319 also used by a lot of commercial apps 204 00:07:02,639 --> 00:07:06,300 that need to have both Windows and Mac 205 00:07:04,319 --> 00:07:08,520 and sometimes Linux clients virtualbox 206 00:07:06,300 --> 00:07:10,919 caliber Mathematica these are all apps 207 00:07:08,520 --> 00:07:12,479 that use QT for their GUI those apps 208 00:07:10,919 --> 00:07:14,400 aren't written in Python but QT has 209 00:07:12,479 --> 00:07:17,100 python bindings actually two of them for 210 00:07:14,400 --> 00:07:18,600 historical reasons gtk is the most 211 00:07:17,100 --> 00:07:19,919 popular GUI toolkit for Linux because 212 00:07:18,600 --> 00:07:21,840 it's the GUI toolkit for The Gnome 213 00:07:19,919 --> 00:07:23,160 desktop environment and essentially 214 00:07:21,840 --> 00:07:25,979 every other desktop environment that 215 00:07:23,160 --> 00:07:28,919 isn't KDE gtk is available on Macos and 216 00:07:25,979 --> 00:07:29,759 windows but it doesn't really work well 217 00:07:28,919 --> 00:07:31,979 there 218 00:07:29,759 --> 00:07:33,660 20 years ago WX widgets was a moderately 219 00:07:31,979 --> 00:07:35,039 popular option it's still around and is 220 00:07:33,660 --> 00:07:36,360 being maintained it's a lot less popular 221 00:07:35,039 --> 00:07:38,220 than it once was 222 00:07:36,360 --> 00:07:40,440 all these toolkits will produce an app 223 00:07:38,220 --> 00:07:41,639 that looks native sometimes that's done 224 00:07:40,440 --> 00:07:43,680 by actually wrapping native 225 00:07:41,639 --> 00:07:45,479 implementations sometimes it's a theme 226 00:07:43,680 --> 00:07:46,919 that tries to fake looking native that 227 00:07:45,479 --> 00:07:49,380 theme may or may not be convincing 228 00:07:46,919 --> 00:07:51,240 depending upon the implementation Kitty 229 00:07:49,380 --> 00:07:52,440 is a cross-platform toolkit that takes a 230 00:07:51,240 --> 00:07:54,599 completely different approach rather 231 00:07:52,440 --> 00:07:56,400 than try to make a KIVI app look native 232 00:07:54,599 --> 00:07:58,680 Kitty takes complete control of the 233 00:07:56,400 --> 00:08:00,780 rendering process a kitty button looks 234 00:07:58,680 --> 00:08:02,400 the same on every platform it never 235 00:08:00,780 --> 00:08:04,500 looks like a native button 236 00:08:02,400 --> 00:08:05,639 then there are gaming toolkits there are 237 00:08:04,500 --> 00:08:06,720 some slight diff these are slightly 238 00:08:05,639 --> 00:08:08,400 different to you know traditional 239 00:08:06,720 --> 00:08:09,780 buttons and text input GUI Frameworks 240 00:08:08,400 --> 00:08:11,819 because they're targeting building games 241 00:08:09,780 --> 00:08:13,979 but they're graphical and you can use 242 00:08:11,819 --> 00:08:16,020 them to build a user interface so 243 00:08:13,979 --> 00:08:17,940 depending upon your needs they might be 244 00:08:16,020 --> 00:08:19,919 the right way to go uh Pi game and 245 00:08:17,940 --> 00:08:22,319 pursued by bear are two examples in the 246 00:08:19,919 --> 00:08:25,080 python space and then there's electron 247 00:08:22,319 --> 00:08:27,360 electron isn't really a GUI toolkit per 248 00:08:25,080 --> 00:08:29,879 se it's a website wearing a trench coat 249 00:08:27,360 --> 00:08:31,800 uh you can build any user experience 250 00:08:29,879 --> 00:08:33,240 you'll want it's it's up to your HTML 251 00:08:31,800 --> 00:08:35,640 styling and JavaScript that you've got 252 00:08:33,240 --> 00:08:37,320 on your web page this can be a viable 253 00:08:35,640 --> 00:08:38,700 way to rapidly develop a cross-platform 254 00:08:37,320 --> 00:08:41,039 user interface especially if you've 255 00:08:38,700 --> 00:08:43,020 already got a team with web skills being 256 00:08:41,039 --> 00:08:44,880 a hybrid you get better access to Native 257 00:08:43,020 --> 00:08:47,220 capabilities than a raw web app would 258 00:08:44,880 --> 00:08:49,560 have but it also has its own trade-offs 259 00:08:47,220 --> 00:08:51,300 memory use is a big one electron apps 260 00:08:49,560 --> 00:08:52,800 also have some very distinct tells from 261 00:08:51,300 --> 00:08:55,800 a user interface point of view that can 262 00:08:52,800 --> 00:08:58,140 be very difficult to mask but it works 263 00:08:55,800 --> 00:08:59,640 whether it works for you that's a 264 00:08:58,140 --> 00:09:02,040 decision you have to make 265 00:08:59,640 --> 00:09:05,040 this is not an exhaustive list there are 266 00:09:02,040 --> 00:09:06,600 others not the least of which is toga if 267 00:09:05,040 --> 00:09:08,279 we've got so many choices you might ask 268 00:09:06,600 --> 00:09:11,040 why did I bother building another one 269 00:09:08,279 --> 00:09:12,899 well firstly platform support of all the 270 00:09:11,040 --> 00:09:14,820 options that I listed previously QT and 271 00:09:12,899 --> 00:09:16,560 kitty are the only two that have any 272 00:09:14,820 --> 00:09:18,720 solution for mobile and at the time I 273 00:09:16,560 --> 00:09:20,519 started toga QT didn't support mobile at 274 00:09:18,720 --> 00:09:22,100 all to the best of my knowledge it still 275 00:09:20,519 --> 00:09:25,200 doesn't have python support for mobile 276 00:09:22,100 --> 00:09:26,820 QT has a webassembly tech demo none of 277 00:09:25,200 --> 00:09:29,040 them have a terminal a console mode back 278 00:09:26,820 --> 00:09:31,380 end toga supports all of those as well 279 00:09:29,040 --> 00:09:33,480 as the desktop platforms secondly toga 280 00:09:31,380 --> 00:09:35,640 is 100 platform native if you are on 281 00:09:33,480 --> 00:09:37,080 Macos and you write an app in Kitty you 282 00:09:35,640 --> 00:09:38,760 can tell it was written in KIVI because 283 00:09:37,080 --> 00:09:40,620 it doesn't look like a Macos app it 284 00:09:38,760 --> 00:09:42,720 looks like a KIVI app if you write a 285 00:09:40,620 --> 00:09:44,220 toga app on Macos it is 286 00:09:42,720 --> 00:09:46,260 indistinguishable from a native app 287 00:09:44,220 --> 00:09:47,519 because you are using the same apis that 288 00:09:46,260 --> 00:09:49,800 you would have used if you'd actually 289 00:09:47,519 --> 00:09:51,180 built a native app in objective-c or or 290 00:09:49,800 --> 00:09:53,459 Swift 291 00:09:51,180 --> 00:09:55,260 why do you care about that well aside 292 00:09:53,459 --> 00:09:58,019 from the Cosmetics you get things like 293 00:09:55,260 --> 00:10:00,180 accessibility for free a toga app will 294 00:09:58,019 --> 00:10:01,620 adapt to Native font sizes color choices 295 00:10:00,180 --> 00:10:02,820 and we'll work out of the box with 296 00:10:01,620 --> 00:10:04,620 screen readers and other assistive 297 00:10:02,820 --> 00:10:06,720 Technologies because the underlying 298 00:10:04,620 --> 00:10:09,420 platform apis support screen readers and 299 00:10:06,720 --> 00:10:11,640 assistive Technologies Kitty doesn't 300 00:10:09,420 --> 00:10:12,839 thirdly it is written in pure python 301 00:10:11,640 --> 00:10:14,220 that means there are no compiled 302 00:10:12,839 --> 00:10:15,839 components this means it's easier to 303 00:10:14,220 --> 00:10:17,940 deploy because there's no binary wheels 304 00:10:15,839 --> 00:10:20,700 or compilation step and it is a lot 305 00:10:17,940 --> 00:10:23,459 smaller the binary wheels for the pi 306 00:10:20,700 --> 00:10:25,680 side Essentials on Macros clocking in at 307 00:10:23,459 --> 00:10:27,540 144 megabytes 308 00:10:25,680 --> 00:10:28,860 if you want a web browser in your app 309 00:10:27,540 --> 00:10:31,080 you're also going to need the add-ons 310 00:10:28,860 --> 00:10:32,279 package and that's an additional 255 311 00:10:31,080 --> 00:10:34,980 megabytes 312 00:10:32,279 --> 00:10:36,600 the whole of toga on Macos including the 313 00:10:34,980 --> 00:10:38,700 web widget is a little over 500 314 00:10:36,600 --> 00:10:40,320 kilobytes 315 00:10:38,700 --> 00:10:42,480 lastly it is an Unapologetic 316 00:10:40,320 --> 00:10:44,579 unapologetically python toolkit written 317 00:10:42,480 --> 00:10:46,920 for python developers that means it uses 318 00:10:44,579 --> 00:10:48,600 python linguistic idiom async await 319 00:10:46,920 --> 00:10:50,279 context managers done to methods the 320 00:10:48,600 --> 00:10:52,800 developer experience has been designed 321 00:10:50,279 --> 00:10:54,839 to be familiar to python developers not 322 00:10:52,800 --> 00:10:56,640 a c plus experience crammed into a 323 00:10:54,839 --> 00:10:58,380 python development environment and 324 00:10:56,640 --> 00:11:00,300 there's no additional domain-specific UI 325 00:10:58,380 --> 00:11:02,279 markup languages or yaml or XML which 326 00:11:00,300 --> 00:11:05,220 you have to learn to make your GUI work 327 00:11:02,279 --> 00:11:07,140 Okay so we've picked a GUI toolkit let's 328 00:11:05,220 --> 00:11:08,640 build an app you might be thinking that 329 00:11:07,140 --> 00:11:10,560 with so many options I couldn't possibly 330 00:11:08,640 --> 00:11:11,940 say anything both meaningful and generic 331 00:11:10,560 --> 00:11:13,680 but the thing is 332 00:11:11,940 --> 00:11:16,200 for the variety all the variety of 333 00:11:13,680 --> 00:11:18,000 options most GUI tool kits are very 334 00:11:16,200 --> 00:11:20,820 similar when it comes to basic workflow 335 00:11:18,000 --> 00:11:23,940 here is the code for a simple toga app 336 00:11:20,820 --> 00:11:25,920 we subclass and app class that app class 337 00:11:23,940 --> 00:11:27,779 has a startup method that runs when the 338 00:11:25,920 --> 00:11:30,300 app starts that startup mechanism 339 00:11:27,779 --> 00:11:31,980 creates a main window you add content to 340 00:11:30,300 --> 00:11:34,380 the main window somehow and then you 341 00:11:31,980 --> 00:11:36,660 show that window the main method of your 342 00:11:34,380 --> 00:11:38,399 app creates an instance of your app and 343 00:11:36,660 --> 00:11:40,500 then starts What's called the main Loop 344 00:11:38,399 --> 00:11:41,760 which runs the applications event Loop 345 00:11:40,500 --> 00:11:43,260 we'll come back to the event Loop but 346 00:11:41,760 --> 00:11:46,019 for now all you need to know is the 347 00:11:43,260 --> 00:11:47,339 event Loop is what runs the app the app 348 00:11:46,019 --> 00:11:48,899 will be displayed when main Loop is 349 00:11:47,339 --> 00:11:51,959 invoked when you exit the app the main 350 00:11:48,899 --> 00:11:54,300 Loop method returns now that's toga but 351 00:11:51,959 --> 00:11:56,940 the code is very similar for almost 352 00:11:54,300 --> 00:11:59,220 every other GUI toolkit here is the same 353 00:11:56,940 --> 00:12:00,959 app written in QT with pi side all of 354 00:11:59,220 --> 00:12:02,579 the widget names start with a queue the 355 00:12:00,959 --> 00:12:04,019 startup method is the dunder in it of 356 00:12:02,579 --> 00:12:05,640 your application application class and 357 00:12:04,019 --> 00:12:07,860 you set Central widget rather than 358 00:12:05,640 --> 00:12:09,540 assigning content and you call xec 359 00:12:07,860 --> 00:12:11,820 rather than main Loop but structurally 360 00:12:09,540 --> 00:12:14,160 it's exactly the same 361 00:12:11,820 --> 00:12:16,140 and here's the same app in TK enter TK 362 00:12:14,160 --> 00:12:17,880 inter convolves the main window and the 363 00:12:16,140 --> 00:12:19,980 app has a single thing so you don't have 364 00:12:17,880 --> 00:12:22,440 to explicitly create the main window but 365 00:12:19,980 --> 00:12:24,600 you create an app you pack content into 366 00:12:22,440 --> 00:12:26,760 the main Window app hybrid and then you 367 00:12:24,600 --> 00:12:28,800 start the main loop again modulo some 368 00:12:26,760 --> 00:12:29,760 fairly minor discrepancies it's the same 369 00:12:28,800 --> 00:12:31,380 code 370 00:12:29,760 --> 00:12:33,060 game toolkits are a little different 371 00:12:31,380 --> 00:12:35,220 because they tend not to have widgets 372 00:12:33,060 --> 00:12:37,380 like button but the basic start app 373 00:12:35,220 --> 00:12:39,959 create Windows start main Loop workflow 374 00:12:37,380 --> 00:12:41,579 definitely exists electron is the odd 375 00:12:39,959 --> 00:12:43,200 one out here it still has a main Loop 376 00:12:41,579 --> 00:12:45,120 but you really don't ever see it 377 00:12:43,200 --> 00:12:46,980 electron is really just starting a web 378 00:12:45,120 --> 00:12:48,480 server and the GUI is rendered pages 379 00:12:46,980 --> 00:12:50,220 from that web server 380 00:12:48,480 --> 00:12:51,540 all right so that's how you set up the 381 00:12:50,220 --> 00:12:55,200 skeleton for an app how does that app 382 00:12:51,540 --> 00:12:55,920 actually you know work well what is an 383 00:12:55,200 --> 00:12:58,740 app 384 00:12:55,920 --> 00:13:00,660 an app is a layout of graphical elements 385 00:12:58,740 --> 00:13:02,399 that respond when the user interacts 386 00:13:00,660 --> 00:13:04,200 with those graphical elements 387 00:13:02,399 --> 00:13:06,180 interacting with resources that are 388 00:13:04,200 --> 00:13:07,860 provided by the host computer your 389 00:13:06,180 --> 00:13:09,360 experience with any given GUI framework 390 00:13:07,860 --> 00:13:10,980 will essentially be governed by how 391 00:13:09,360 --> 00:13:12,779 simple or difficult the framework makes 392 00:13:10,980 --> 00:13:15,180 those three tasks 393 00:13:12,779 --> 00:13:16,620 so first off we need a layout of 394 00:13:15,180 --> 00:13:18,779 graphical elements you need to describe 395 00:13:16,620 --> 00:13:21,000 what widgets are visible and where they 396 00:13:18,779 --> 00:13:22,500 are visible every toolkit has a very 397 00:13:21,000 --> 00:13:25,139 slightly way of doing this but there are 398 00:13:22,500 --> 00:13:26,639 some very common General themes most GUI 399 00:13:25,139 --> 00:13:28,320 toolkits when you do their you know 400 00:13:26,639 --> 00:13:29,820 hello World tutorial will introduce you 401 00:13:28,320 --> 00:13:31,680 to some sort of box packing model 402 00:13:29,820 --> 00:13:34,440 whether or not they call it that this is 403 00:13:31,680 --> 00:13:36,839 some container and you pack content into 404 00:13:34,440 --> 00:13:38,160 that container that packing process will 405 00:13:36,839 --> 00:13:39,779 usually have some sort of controller 406 00:13:38,160 --> 00:13:41,519 whether you're packing horizontally or 407 00:13:39,779 --> 00:13:43,019 vertically whether a new object is 408 00:13:41,519 --> 00:13:45,300 packed at the start or the end of the 409 00:13:43,019 --> 00:13:46,920 container of the packing content the 410 00:13:45,300 --> 00:13:48,360 containers are usually hierarchical so 411 00:13:46,920 --> 00:13:50,040 you can pack a horizontal container 412 00:13:48,360 --> 00:13:51,600 inside a vertical container inside a 413 00:13:50,040 --> 00:13:52,740 horizontal container and so on as you 414 00:13:51,600 --> 00:13:55,680 need to go 415 00:13:52,740 --> 00:13:57,180 Dom based layout is somewhat like a box 416 00:13:55,680 --> 00:13:59,160 packing model except that instead of 417 00:13:57,180 --> 00:14:01,320 explicitly putting a widget inside a 418 00:13:59,160 --> 00:14:03,540 horizontal box inside a vertical box you 419 00:14:01,320 --> 00:14:05,760 build a hierarchy of content and then 420 00:14:03,540 --> 00:14:07,740 apply layout rules to that content or to 421 00:14:05,760 --> 00:14:09,899 that hierarchy this will often involve 422 00:14:07,740 --> 00:14:12,019 designated some content as horizontal or 423 00:14:09,899 --> 00:14:14,579 vertical boxes but it doesn't require it 424 00:14:12,019 --> 00:14:16,620 css3 flexbox and grid layouts for 425 00:14:14,579 --> 00:14:18,660 example are both layered over the top of 426 00:14:16,620 --> 00:14:20,700 a Dom the hierarchical definition of 427 00:14:18,660 --> 00:14:22,800 content but the specifics of where 428 00:14:20,700 --> 00:14:24,959 children of that tree that hierarchy 429 00:14:22,800 --> 00:14:26,579 live appear where they appear relative 430 00:14:24,959 --> 00:14:29,399 to their parents is determined by 431 00:14:26,579 --> 00:14:31,200 styling rules electron being a website 432 00:14:29,399 --> 00:14:34,079 in a trench coat uses a non-model 433 00:14:31,200 --> 00:14:36,480 because it's literally HTML and CSS so 434 00:14:34,079 --> 00:14:38,700 does toga toga doesn't literally use CSS 435 00:14:36,480 --> 00:14:41,459 it uses a reduced CSS subset called Pac 436 00:14:38,700 --> 00:14:43,500 but pack has a direct mapping to css3 437 00:14:41,459 --> 00:14:45,060 flexbox rules and toga has been designed 438 00:14:43,500 --> 00:14:46,800 in such a way that the intention is in 439 00:14:45,060 --> 00:14:49,860 the future we will be able to drop in an 440 00:14:46,800 --> 00:14:51,720 actual full css3 engine into toga 441 00:14:49,860 --> 00:14:53,519 another common approach is a grid layout 442 00:14:51,720 --> 00:14:55,620 this is essentially the same as HTML 443 00:14:53,519 --> 00:14:57,240 tables you describe how many columns and 444 00:14:55,620 --> 00:14:59,279 rows exist in your layout you place 445 00:14:57,240 --> 00:15:00,899 widgets in that layout at a specific row 446 00:14:59,279 --> 00:15:02,579 or column depending on your GUI 447 00:15:00,899 --> 00:15:04,680 framework widgets maybe how to span 448 00:15:02,579 --> 00:15:06,360 multiple columns or multiple rows and 449 00:15:04,680 --> 00:15:08,760 then you define how the grid is allowed 450 00:15:06,360 --> 00:15:10,860 to resize are all columns the same fixed 451 00:15:08,760 --> 00:15:12,899 width or is column one exactly 100 452 00:15:10,860 --> 00:15:15,480 pixels wide and column two is twice the 453 00:15:12,899 --> 00:15:17,100 width of column three things like that 454 00:15:15,480 --> 00:15:19,139 a less common approach is something 455 00:15:17,100 --> 00:15:20,639 called constraint based layout in a 456 00:15:19,139 --> 00:15:22,980 constraint-based layout all the content 457 00:15:20,639 --> 00:15:24,300 is thrown into a big unsorted bag but 458 00:15:22,980 --> 00:15:26,760 then you specify mathematical 459 00:15:24,300 --> 00:15:28,980 constraints on the final layout button 460 00:15:26,760 --> 00:15:30,779 one must be 100 pixels wide the left of 461 00:15:28,980 --> 00:15:32,339 button one must be 10 pixels from the 462 00:15:30,779 --> 00:15:33,839 side of the window the left of button 463 00:15:32,339 --> 00:15:35,940 two must be 20 pixels from the right 464 00:15:33,839 --> 00:15:39,000 side of button one the layout algorithm 465 00:15:35,940 --> 00:15:40,260 is then literally told sulfur X in that 466 00:15:39,000 --> 00:15:41,760 case it would mean or in this case here 467 00:15:40,260 --> 00:15:43,440 it would mean that button one is at x 468 00:15:41,760 --> 00:15:45,959 equals 10 and button two is at x equals 469 00:15:43,440 --> 00:15:48,779 130. constraint based layouts are 470 00:15:45,959 --> 00:15:50,880 incredibly flexible and very responsive 471 00:15:48,779 --> 00:15:53,160 but it's also easy to end up with an 472 00:15:50,880 --> 00:15:54,839 over or under constrained layout where a 473 00:15:53,160 --> 00:15:57,240 layout isn't working it's nearly 474 00:15:54,839 --> 00:15:58,800 inscrutable to work out why you are 475 00:15:57,240 --> 00:16:00,300 literally trying to debug a complex 476 00:15:58,800 --> 00:16:01,980 linear algebra problem where all you've 477 00:16:00,300 --> 00:16:04,639 got is the wrong answer and a layout 478 00:16:01,980 --> 00:16:04,639 that doesn't work 479 00:16:04,980 --> 00:16:09,540 on your GUI toolkit you can 480 00:16:07,680 --> 00:16:11,160 mirror grid inside your box packing 481 00:16:09,540 --> 00:16:12,660 layout for example but it's not the only 482 00:16:11,160 --> 00:16:14,160 layout consideration you also need to 483 00:16:12,660 --> 00:16:15,839 think about how you're going to adapt to 484 00:16:14,160 --> 00:16:17,220 different sizing for anyone with a web 485 00:16:15,839 --> 00:16:19,500 design background this won't be a new 486 00:16:17,220 --> 00:16:21,300 idea what if any constraints are you 487 00:16:19,500 --> 00:16:23,940 going to impose on window size and how 488 00:16:21,300 --> 00:16:26,040 will content in the window adapt to 489 00:16:23,940 --> 00:16:28,079 sizes in window size this is an area 490 00:16:26,040 --> 00:16:29,220 where Dom and constraint based layouts 491 00:16:28,079 --> 00:16:30,839 have an advantage because you can Define 492 00:16:29,220 --> 00:16:33,720 different CSS rules for different 493 00:16:30,839 --> 00:16:35,220 widgets window sizes or rely on loosely 494 00:16:33,720 --> 00:16:36,540 defined constraint rules to find 495 00:16:35,220 --> 00:16:39,420 different solutions to the layout 496 00:16:36,540 --> 00:16:41,519 depending upon the input window size 497 00:16:39,420 --> 00:16:42,959 but completely aside from layout you 498 00:16:41,519 --> 00:16:44,759 need to think about look and feel if you 499 00:16:42,959 --> 00:16:46,259 are building a cross-platform app are 500 00:16:44,759 --> 00:16:48,420 you going to try to try to make that app 501 00:16:46,259 --> 00:16:50,339 look the same everywhere or make the app 502 00:16:48,420 --> 00:16:53,040 look as native as possible everywhere 503 00:16:50,339 --> 00:16:56,940 now this is an area where I have 504 00:16:53,040 --> 00:16:58,320 opinions uh I despise personally apps 505 00:16:56,940 --> 00:16:59,820 that decide that they know better than 506 00:16:58,320 --> 00:17:01,620 the operating system what a button 507 00:16:59,820 --> 00:17:03,420 should look like my experience has been 508 00:17:01,620 --> 00:17:05,040 that apps that have a common look and 509 00:17:03,420 --> 00:17:06,839 feel everywhere are the Hallmark of 510 00:17:05,040 --> 00:17:09,240 either lazy or under resourced 511 00:17:06,839 --> 00:17:11,100 developers to me commonality in parent 512 00:17:09,240 --> 00:17:13,620 in appearance is a form of implicit 513 00:17:11,100 --> 00:17:15,480 documentation if your apps buttons look 514 00:17:13,620 --> 00:17:17,760 like every other button on every other 515 00:17:15,480 --> 00:17:20,040 app in my operating system then I know 516 00:17:17,760 --> 00:17:21,600 when and how they can be pressed and I 517 00:17:20,040 --> 00:17:24,000 know how they will respond when they are 518 00:17:21,600 --> 00:17:25,679 pressed if your UI designer has come up 519 00:17:24,000 --> 00:17:26,819 with a whole new visual concept for 520 00:17:25,679 --> 00:17:29,160 pressing this 521 00:17:26,819 --> 00:17:30,840 I need to learn what that is and that 522 00:17:29,160 --> 00:17:32,880 slows me down and when it comes to 523 00:17:30,840 --> 00:17:35,520 things like how keyboard shortcuts work 524 00:17:32,880 --> 00:17:38,039 in a text area it can be a major 525 00:17:35,520 --> 00:17:40,559 impediment to productivity 526 00:17:38,039 --> 00:17:42,059 the one case I will begrudgingly make 527 00:17:40,559 --> 00:17:43,500 for guis being visually consistent 528 00:17:42,059 --> 00:17:45,419 across platforms is in settings like 529 00:17:43,500 --> 00:17:47,280 education where you want screenshots of 530 00:17:45,419 --> 00:17:49,380 your app to be consistent with exactly 531 00:17:47,280 --> 00:17:52,320 what the user sees on every platform 532 00:17:49,380 --> 00:17:54,539 however even then I would argue that 533 00:17:52,320 --> 00:17:56,039 Beyond basic introductory material you 534 00:17:54,539 --> 00:17:57,720 are doing your users a disservice by 535 00:17:56,039 --> 00:18:00,299 trying to mask platform conventions 536 00:17:57,720 --> 00:18:02,400 under a facade and inevitably when you 537 00:18:00,299 --> 00:18:04,380 hide platform defaults you also hide 538 00:18:02,400 --> 00:18:05,640 platform accessibility affordances and 539 00:18:04,380 --> 00:18:07,919 all the little details that make 540 00:18:05,640 --> 00:18:10,620 computers easy to use 541 00:18:07,919 --> 00:18:12,120 whether you agree with me or not this is 542 00:18:10,620 --> 00:18:14,340 an area where your GUI toolkit will 543 00:18:12,120 --> 00:18:15,720 constrain your options KIVI is all in on 544 00:18:14,340 --> 00:18:18,299 making your GUI look the same on every 545 00:18:15,720 --> 00:18:20,460 platform gtk has a default look and feel 546 00:18:18,299 --> 00:18:22,679 but it can be extensively themed toga 547 00:18:20,460 --> 00:18:24,840 has very limited styling options some 548 00:18:22,679 --> 00:18:27,000 basic size and color controls but you 549 00:18:24,840 --> 00:18:28,260 can't make a button look rounded if the 550 00:18:27,000 --> 00:18:29,940 Platinum platform doesn't give you 551 00:18:28,260 --> 00:18:30,960 rounded buttons you don't get rounded 552 00:18:29,940 --> 00:18:33,059 buttons 553 00:18:30,960 --> 00:18:35,160 so that's layout going back to our 554 00:18:33,059 --> 00:18:36,720 description of an app our app responds 555 00:18:35,160 --> 00:18:38,280 to user interactions with elements in 556 00:18:36,720 --> 00:18:39,660 our layout now earlier when I spoke 557 00:18:38,280 --> 00:18:41,760 about starting the app I mentioned the 558 00:18:39,660 --> 00:18:44,160 event loop as being what runs the app 559 00:18:41,760 --> 00:18:46,080 let's peel back the lid on an ISO 560 00:18:44,160 --> 00:18:47,039 standard GUI app and see what we find 561 00:18:46,080 --> 00:18:49,080 inside 562 00:18:47,039 --> 00:18:51,840 no matter the GUI framework what you 563 00:18:49,080 --> 00:18:53,700 will essentially find is this when you 564 00:18:51,840 --> 00:18:56,460 invoke the main Loop the startup method 565 00:18:53,700 --> 00:18:58,919 is invoked which creates the GUI then 566 00:18:56,460 --> 00:19:00,840 you start a literal loop the loop is 567 00:18:58,919 --> 00:19:03,840 essentially while not quit process 568 00:19:00,840 --> 00:19:05,580 events redraw every time you click on a 569 00:19:03,840 --> 00:19:07,380 button type a character drag the corner 570 00:19:05,580 --> 00:19:09,660 of a window to resize it that's an event 571 00:19:07,380 --> 00:19:11,700 and the app code will respond to each of 572 00:19:09,660 --> 00:19:13,080 those events in turn redrawing any part 573 00:19:11,700 --> 00:19:14,280 of the window that requires a visual 574 00:19:13,080 --> 00:19:16,679 change 575 00:19:14,280 --> 00:19:19,440 now this isn't actually the code of any 576 00:19:16,679 --> 00:19:20,480 GUI framework but it's also not that far 577 00:19:19,440 --> 00:19:23,340 off 578 00:19:20,480 --> 00:19:25,679 the important thing to note is that when 579 00:19:23,340 --> 00:19:27,660 an app is redrawing it's not processing 580 00:19:25,679 --> 00:19:29,580 events and when it's processing events 581 00:19:27,660 --> 00:19:33,179 it's not redrawing 582 00:19:29,580 --> 00:19:34,679 who has ever seen an app beach ball 583 00:19:33,179 --> 00:19:36,480 yeah all right 584 00:19:34,679 --> 00:19:38,820 ever wondered what's happening 585 00:19:36,480 --> 00:19:41,039 this is what's happening your app is 586 00:19:38,820 --> 00:19:43,620 trying to process an event and it's 587 00:19:41,039 --> 00:19:46,260 taking too long and it hasn't redrawn in 588 00:19:43,620 --> 00:19:47,640 a while for some measure of a while and 589 00:19:46,260 --> 00:19:49,380 so the operating system tells you 590 00:19:47,640 --> 00:19:51,360 there's a problem by showing you a 591 00:19:49,380 --> 00:19:53,100 little beach ball icon 592 00:19:51,360 --> 00:19:55,440 beach ball is very easy to generate 593 00:19:53,100 --> 00:19:57,600 let's add a button to our GUI and say 594 00:19:55,440 --> 00:19:59,640 that when the Press event occurs we want 595 00:19:57,600 --> 00:20:01,919 to download a movie and in our event 596 00:19:59,640 --> 00:20:04,080 handler we use requests to download the 597 00:20:01,919 --> 00:20:05,340 URL the movie photo was large so that 598 00:20:04,080 --> 00:20:06,000 download is going to take a minute or 599 00:20:05,340 --> 00:20:08,220 two 600 00:20:06,000 --> 00:20:10,400 we run our app we push the button and we 601 00:20:08,220 --> 00:20:13,260 get a beach ball why because 602 00:20:10,400 --> 00:20:15,120 requests.get is a blocking method the 603 00:20:13,260 --> 00:20:17,640 event handler has been called but it 604 00:20:15,120 --> 00:20:19,799 won't return until the download has 605 00:20:17,640 --> 00:20:23,100 finished and until the event handler is 606 00:20:19,799 --> 00:20:24,780 returned the GUI can't redraw so 607 00:20:23,100 --> 00:20:25,860 obviously we need to do something 608 00:20:24,780 --> 00:20:28,740 different here 609 00:20:25,860 --> 00:20:30,299 First Option use threads now as soon as 610 00:20:28,740 --> 00:20:32,100 the threads get involved the gods have a 611 00:20:30,299 --> 00:20:33,600 little chuckle threat execution can be 612 00:20:32,100 --> 00:20:35,220 unpredictable and therefore very hard to 613 00:20:33,600 --> 00:20:36,539 debug the old joke is that if you're a 614 00:20:35,220 --> 00:20:37,919 developer with a problem and you solve 615 00:20:36,539 --> 00:20:39,419 your problem with threads problems now 616 00:20:37,919 --> 00:20:41,280 too have you 617 00:20:39,419 --> 00:20:42,900 the other thing to consider is that a 618 00:20:41,280 --> 00:20:44,400 lot of GUI toolkits have a very complex 619 00:20:42,900 --> 00:20:45,960 relationship with threats the thread 620 00:20:44,400 --> 00:20:48,900 that runs the event Loop is called the 621 00:20:45,960 --> 00:20:51,000 GUI thread so something simple like when 622 00:20:48,900 --> 00:20:52,620 the down sorry the many GUI Frameworks 623 00:20:51,000 --> 00:20:56,100 will only allow you to invoke GUI 624 00:20:52,620 --> 00:20:57,539 actions on a GUI thread so something 625 00:20:56,100 --> 00:21:00,419 simple like when the download is 626 00:20:57,539 --> 00:21:01,919 complete update the status bar becomes a 627 00:21:00,419 --> 00:21:04,320 lot more complicated because you can't 628 00:21:01,919 --> 00:21:05,940 update the GUI from the thread that is 629 00:21:04,320 --> 00:21:08,039 doing the download 630 00:21:05,940 --> 00:21:09,900 the usual solution for this is the GUI 631 00:21:08,039 --> 00:21:11,460 toolkit will provide some way to post an 632 00:21:09,900 --> 00:21:13,559 event to the main thread so you wrap up 633 00:21:11,460 --> 00:21:15,360 your update the status bar logic into a 634 00:21:13,559 --> 00:21:17,160 function of some kind and then post that 635 00:21:15,360 --> 00:21:19,380 function to the GUI thread so it can be 636 00:21:17,160 --> 00:21:21,360 executed there almost as if it was a 637 00:21:19,380 --> 00:21:22,740 user generated event 638 00:21:21,360 --> 00:21:24,360 the second approach is to break whatever 639 00:21:22,740 --> 00:21:26,460 you're doing down into chunks and then 640 00:21:24,360 --> 00:21:27,840 explicitly Release Control back to the 641 00:21:26,460 --> 00:21:29,340 main event loop on a regular basis 642 00:21:27,840 --> 00:21:31,440 there's no problem doing complex 643 00:21:29,340 --> 00:21:33,360 calculations in the GUI thread you just 644 00:21:31,440 --> 00:21:34,799 can't monopolize the GUI threads time 645 00:21:33,360 --> 00:21:37,320 you've got a release control back so it 646 00:21:34,799 --> 00:21:38,940 can redraw so most GUI toolkits will 647 00:21:37,320 --> 00:21:41,520 have some sort of mechanism to either 648 00:21:38,940 --> 00:21:43,740 explicitly explicitly run an iteration 649 00:21:41,520 --> 00:21:45,780 of the main Loop or Release Control back 650 00:21:43,740 --> 00:21:48,059 to the main Loop in some way 651 00:21:45,780 --> 00:21:49,559 for example in toga because it's a 652 00:21:48,059 --> 00:21:50,880 python first toolkit you do this by 653 00:21:49,559 --> 00:21:52,919 turning your event handler into a 654 00:21:50,880 --> 00:21:54,179 generator and yielding it tells the 655 00:21:52,919 --> 00:21:55,559 event handler you can give control back 656 00:21:54,179 --> 00:21:57,240 to the event Loop now and then resume 657 00:21:55,559 --> 00:22:00,480 processing as soon as you as soon as you 658 00:21:57,240 --> 00:22:02,340 can as long as the gap between yields is 659 00:22:00,480 --> 00:22:03,960 relatively short sort of 0.1 of a second 660 00:22:02,340 --> 00:22:06,179 There's A good rule of thumb is an upper 661 00:22:03,960 --> 00:22:08,220 limit this can work really well 662 00:22:06,179 --> 00:22:10,320 better approach still go asynchronous 663 00:22:08,220 --> 00:22:11,400 guis are almost literally the poster 664 00:22:10,320 --> 00:22:13,320 child for why you care about 665 00:22:11,400 --> 00:22:14,520 asynchronous behavior in your app while 666 00:22:13,320 --> 00:22:16,080 you're waiting for something to happen 667 00:22:14,520 --> 00:22:17,460 you don't have to block the app for 668 00:22:16,080 --> 00:22:19,320 doing something else like redrawing 669 00:22:17,460 --> 00:22:21,539 Release Control back to the GUI app let 670 00:22:19,320 --> 00:22:23,580 me resume when the result is ready most 671 00:22:21,539 --> 00:22:25,020 python GUI toolkits don't support async 672 00:22:23,580 --> 00:22:26,460 Behavior natively either for historical 673 00:22:25,020 --> 00:22:28,440 reasons or because the languages they're 674 00:22:26,460 --> 00:22:30,120 built in usually C or C plus plus or 675 00:22:28,440 --> 00:22:32,159 derivatives don't have native 676 00:22:30,120 --> 00:22:34,440 asynchronous language constructs but 677 00:22:32,159 --> 00:22:36,419 python is a language a toga is a python 678 00:22:34,440 --> 00:22:38,340 first toolkit so any event handler can 679 00:22:36,419 --> 00:22:40,140 be an asynchronous Co routine you need 680 00:22:38,340 --> 00:22:41,460 to Source your async libraries for any 681 00:22:40,140 --> 00:22:43,980 blocking Behavior so you can't use 682 00:22:41,460 --> 00:22:45,780 requests for HTTP retrieval my 683 00:22:43,980 --> 00:22:48,900 suggestion would be use either hdbx or 684 00:22:45,780 --> 00:22:51,120 AIO HTTP but as long as you can find an 685 00:22:48,900 --> 00:22:52,500 async library to do your busy work this 686 00:22:51,120 --> 00:22:54,720 works really well 687 00:22:52,500 --> 00:22:56,220 so that's event handlers and the event 688 00:22:54,720 --> 00:22:57,720 Loop they're responding to explicit 689 00:22:56,220 --> 00:22:59,220 interactions from a user what about 690 00:22:57,720 --> 00:23:00,720 background workers I want something to 691 00:22:59,220 --> 00:23:03,419 run in the background upgrading the GUI 692 00:23:00,720 --> 00:23:05,760 once a second well same rules apply you 693 00:23:03,419 --> 00:23:07,679 can't put a while true sleep One update 694 00:23:05,760 --> 00:23:09,240 into your code because that will block 695 00:23:07,679 --> 00:23:11,760 the event Loop so you need a different 696 00:23:09,240 --> 00:23:13,320 approach again you can use threads with 697 00:23:11,760 --> 00:23:14,640 the same caveats as before another 698 00:23:13,320 --> 00:23:16,440 common approach is something called a 699 00:23:14,640 --> 00:23:18,659 timeout function you invoke the function 700 00:23:16,440 --> 00:23:20,220 on the main Loop that says call this 701 00:23:18,659 --> 00:23:21,720 other function in one second and when 702 00:23:20,220 --> 00:23:23,159 that other function finishes the last 703 00:23:21,720 --> 00:23:24,179 thing it does is say call me again in 704 00:23:23,159 --> 00:23:25,799 one second 705 00:23:24,179 --> 00:23:27,659 it's a bit like the way you post methods 706 00:23:25,799 --> 00:23:29,760 from a worker thread uh from the for the 707 00:23:27,659 --> 00:23:31,140 main Loop when the GUI updates except 708 00:23:29,760 --> 00:23:33,419 that there's a delay between invocation 709 00:23:31,140 --> 00:23:35,039 and execution or if your GUI toolkit 710 00:23:33,419 --> 00:23:36,900 allows you can also Define a Cooperative 711 00:23:35,039 --> 00:23:38,820 or asynchronous background Handler after 712 00:23:36,900 --> 00:23:40,200 all what is a background worker but a 713 00:23:38,820 --> 00:23:41,520 persistent button Handler where the 714 00:23:40,200 --> 00:23:43,799 button is pressed for you when you start 715 00:23:41,520 --> 00:23:46,080 the app the only cut only caveat you 716 00:23:43,799 --> 00:23:48,539 can't use time.sleep because that's a 717 00:23:46,080 --> 00:23:50,280 blocking method but you can use a weight 718 00:23:48,539 --> 00:23:52,380 async io.sleep because that's 719 00:23:50,280 --> 00:23:54,000 non-blocking 720 00:23:52,380 --> 00:23:55,320 all right sorry we've got a layout we're 721 00:23:54,000 --> 00:23:56,580 doing work in response to user 722 00:23:55,320 --> 00:23:57,840 interactions but we're going to need to 723 00:23:56,580 --> 00:23:59,520 interact with the resources on the host 724 00:23:57,840 --> 00:24:00,360 computer there's really only one thing 725 00:23:59,520 --> 00:24:02,340 you need to know when it comes to 726 00:24:00,360 --> 00:24:04,260 dealing with app resources there is no 727 00:24:02,340 --> 00:24:05,840 current working directory when you write 728 00:24:04,260 --> 00:24:09,240 a Python program that says open 729 00:24:05,840 --> 00:24:12,000 myfile.txt myfile.txt is being specified 730 00:24:09,240 --> 00:24:14,760 as a relative path not an absolute path 731 00:24:12,000 --> 00:24:16,020 it's implied that any relative path will 732 00:24:14,760 --> 00:24:17,820 be resolved relative to your current 733 00:24:16,020 --> 00:24:19,260 working directory which is basically the 734 00:24:17,820 --> 00:24:21,299 directory from which you started your 735 00:24:19,260 --> 00:24:23,280 python interpreter when you start an app 736 00:24:21,299 --> 00:24:25,320 from your taskbar what's the current 737 00:24:23,280 --> 00:24:27,059 working directory is it the location of 738 00:24:25,320 --> 00:24:28,620 the app is it the user's home directory 739 00:24:27,059 --> 00:24:31,200 the last folder you would open your file 740 00:24:28,620 --> 00:24:32,460 manager the root of the file system who 741 00:24:31,200 --> 00:24:34,620 knows 742 00:24:32,460 --> 00:24:36,659 essentially if you do anything with past 743 00:24:34,620 --> 00:24:38,760 in your app you must use absolute Parts 744 00:24:36,659 --> 00:24:41,280 worst case you can use done to file on 745 00:24:38,760 --> 00:24:42,960 your python source code but most GUI GUI 746 00:24:41,280 --> 00:24:45,240 toolkits will give you some way to get 747 00:24:42,960 --> 00:24:46,799 an absolute path anchor of some kind a 748 00:24:45,240 --> 00:24:48,360 no known path that is associated with 749 00:24:46,799 --> 00:24:50,100 the app a resource folder or something 750 00:24:48,360 --> 00:24:51,780 like that toga for example provides 751 00:24:50,100 --> 00:24:53,460 app.parts that gives you a whole bunch 752 00:24:51,780 --> 00:24:56,220 of known paths that you can use as 753 00:24:53,460 --> 00:24:58,380 anchors as path live objects 754 00:24:56,220 --> 00:24:59,640 so you've built your app but any good 755 00:24:58,380 --> 00:25:01,260 engineering is not just about building 756 00:24:59,640 --> 00:25:02,880 it's about testing as well how do you 757 00:25:01,260 --> 00:25:04,980 test a GUI app 758 00:25:02,880 --> 00:25:06,900 the bad news here is that GUI testing is 759 00:25:04,980 --> 00:25:09,480 a bit of a nightmare there is 760 00:25:06,900 --> 00:25:12,120 essentially no analog of selenium or 761 00:25:09,480 --> 00:25:14,400 plainright for poking a GUI in a 762 00:25:12,120 --> 00:25:16,320 cross-platform way there are platform 763 00:25:14,400 --> 00:25:18,120 specific Solutions but some of them cost 764 00:25:16,320 --> 00:25:20,760 a lot of money and they're all a bit 765 00:25:18,120 --> 00:25:22,679 messy so your best bet is to clearly 766 00:25:20,760 --> 00:25:24,179 separate GUI logic from business logic 767 00:25:22,679 --> 00:25:25,679 use automated testing for all the 768 00:25:24,179 --> 00:25:27,480 business logic interface and then use 769 00:25:25,679 --> 00:25:29,220 manual testing as a final integration or 770 00:25:27,480 --> 00:25:31,020 acceptance test there are many 771 00:25:29,220 --> 00:25:33,000 application design patterns for this 772 00:25:31,020 --> 00:25:35,039 model view controller model model view 773 00:25:33,000 --> 00:25:37,320 view model model view presenter picking 774 00:25:35,039 --> 00:25:38,700 one of those is a talk unto itself and 775 00:25:37,320 --> 00:25:40,620 your choice of GUI toolkit might 776 00:25:38,700 --> 00:25:41,940 influence your choice the key thing is 777 00:25:40,620 --> 00:25:43,159 that you have to have a clear testable 778 00:25:41,940 --> 00:25:46,020 interface 779 00:25:43,159 --> 00:25:48,539 so that you can test assuming the button 780 00:25:46,020 --> 00:25:50,159 is pushed what logic will be executed 781 00:25:48,539 --> 00:25:52,559 and what changes might be affected in 782 00:25:50,159 --> 00:25:54,179 the GUI this is also an area where your 783 00:25:52,559 --> 00:25:56,400 GUI toolkit might be able to help you 784 00:25:54,179 --> 00:25:58,860 toga for example is a cross-platform 785 00:25:56,400 --> 00:26:01,559 toolkit and one of those platforms is a 786 00:25:58,860 --> 00:26:03,539 dummy a back end that satisfies the API 787 00:26:01,559 --> 00:26:05,940 contract of a back end but doesn't 788 00:26:03,539 --> 00:26:07,919 actually display anything it but what it 789 00:26:05,940 --> 00:26:09,720 does do is expose an auditable log of 790 00:26:07,919 --> 00:26:12,299 all the GUI actions that have been 791 00:26:09,720 --> 00:26:14,279 performed toga guarantees that the real 792 00:26:12,299 --> 00:26:16,320 back ends will do the same thing as the 793 00:26:14,279 --> 00:26:18,059 dummy back end as part of its own 794 00:26:16,320 --> 00:26:20,400 testing so if you can validate that your 795 00:26:18,059 --> 00:26:22,020 app works with a dummy backend you 796 00:26:20,400 --> 00:26:23,520 should only require some light final 797 00:26:22,020 --> 00:26:25,260 acceptance testing 798 00:26:23,520 --> 00:26:27,000 also remember that you should probably 799 00:26:25,260 --> 00:26:28,440 be running your tests on the platform 800 00:26:27,000 --> 00:26:29,940 where the apps will run so if you're 801 00:26:28,440 --> 00:26:32,880 building a mobile app that means you 802 00:26:29,940 --> 00:26:34,500 need to run your tests on a phone if 803 00:26:32,880 --> 00:26:36,120 you're building a mobile sorry beware 804 00:26:34,500 --> 00:26:37,980 can be some help here briefcase which is 805 00:26:36,120 --> 00:26:39,240 beware's app deployment tool has a 806 00:26:37,980 --> 00:26:42,179 testing mode that can be used to run 807 00:26:39,240 --> 00:26:44,279 apps on app tests on mobile devices and 808 00:26:42,179 --> 00:26:46,260 mobile device simulators including NCI 809 00:26:44,279 --> 00:26:48,659 and briefcase isn't limited to working 810 00:26:46,260 --> 00:26:50,520 with toga 811 00:26:48,659 --> 00:26:51,720 all right so what if you're elbow deep 812 00:26:50,520 --> 00:26:52,860 in your cross-platform app and you 813 00:26:51,720 --> 00:26:54,480 discover that there's some capability 814 00:26:52,860 --> 00:26:57,059 that your platform has but your GUI 815 00:26:54,480 --> 00:26:59,580 toolkit doesn't well any cross-platform 816 00:26:57,059 --> 00:27:01,559 to a toolkit is a layer on top of system 817 00:26:59,580 --> 00:27:03,240 native libraries at some level if your 818 00:27:01,559 --> 00:27:05,700 toolkit doesn't expose a feature you 819 00:27:03,240 --> 00:27:07,020 need go straight to the source call the 820 00:27:05,700 --> 00:27:08,940 native system libraries to do whatever 821 00:27:07,020 --> 00:27:10,260 you need to do there is always a way to 822 00:27:08,940 --> 00:27:13,140 get a handle to those native system 823 00:27:10,260 --> 00:27:14,340 libraries sometimes multiple ways and in 824 00:27:13,140 --> 00:27:17,220 the worst case you can almost always 825 00:27:14,340 --> 00:27:18,860 fall back to raw ffi and C types to 826 00:27:17,220 --> 00:27:21,299 invoke functions in a binary library 827 00:27:18,860 --> 00:27:23,039 that code that you write won't be 828 00:27:21,299 --> 00:27:25,320 cross-platform so you'll need likely 829 00:27:23,039 --> 00:27:29,159 need to add your ifs dot platform equals 830 00:27:25,320 --> 00:27:30,360 macros type guards you also need to get 831 00:27:29,159 --> 00:27:32,159 familiar with reading Objective C 832 00:27:30,360 --> 00:27:33,419 documentation and converting it into the 833 00:27:32,159 --> 00:27:35,100 equivalent python or you know whatever 834 00:27:33,419 --> 00:27:36,779 platform language you need to know but 835 00:27:35,100 --> 00:27:38,640 it's also not as hard as you might think 836 00:27:36,779 --> 00:27:40,440 for what it's worth toga Express 837 00:27:38,640 --> 00:27:41,760 provides explicit access to these layers 838 00:27:40,440 --> 00:27:42,779 if you've got a toga widget you can 839 00:27:41,760 --> 00:27:44,039 always get a handle to the native 840 00:27:42,779 --> 00:27:45,360 widgets that are being used to implement 841 00:27:44,039 --> 00:27:47,220 the toga widget 842 00:27:45,360 --> 00:27:48,720 this is true to varying degrees of other 843 00:27:47,220 --> 00:27:50,100 cross-platform toolkits check local 844 00:27:48,720 --> 00:27:51,960 guide for details 845 00:27:50,100 --> 00:27:53,100 but as we did in the beginning sometimes 846 00:27:51,960 --> 00:27:54,659 it's important to interrogate your 847 00:27:53,100 --> 00:27:56,580 original premise maybe a cross-platform 848 00:27:54,659 --> 00:27:58,620 toolkit isn't what you need a 849 00:27:56,580 --> 00:28:00,299 cross-platform toolkit is by its very 850 00:27:58,620 --> 00:28:02,400 nature and abstraction this means fine 851 00:28:00,299 --> 00:28:03,480 details get lost if you're reaching a 852 00:28:02,400 --> 00:28:04,980 point where you care about those fine 853 00:28:03,480 --> 00:28:06,179 details maybe it's time to consider 854 00:28:04,980 --> 00:28:07,799 whether you should abandon your 855 00:28:06,179 --> 00:28:09,480 cross-platform toolkit and see whether 856 00:28:07,799 --> 00:28:11,700 you can build a common logic core that's 857 00:28:09,480 --> 00:28:13,500 then shared between specific front-ends 858 00:28:11,700 --> 00:28:15,419 this also doesn't mean you have to leave 859 00:28:13,500 --> 00:28:16,860 python toga is a cross-platform toolkit 860 00:28:15,419 --> 00:28:18,659 but you could build a native 861 00:28:16,860 --> 00:28:20,700 platform-specific app using Rubicon 862 00:28:18,659 --> 00:28:23,340 objective-c tracker pythg object to 863 00:28:20,700 --> 00:28:26,220 python.net toolkits that at over users 864 00:28:23,340 --> 00:28:28,260 to access its local systems 865 00:28:26,220 --> 00:28:29,460 so that's a lightning tour of the things 866 00:28:28,260 --> 00:28:31,260 you need to consider when building a 867 00:28:29,460 --> 00:28:32,279 cross-platform GUI app in Python if you 868 00:28:31,260 --> 00:28:33,360 want to know more you want to try this 869 00:28:32,279 --> 00:28:35,760 out for yourself I recommend going 870 00:28:33,360 --> 00:28:36,900 through the beware tutorial.com that 871 00:28:35,760 --> 00:28:38,279 will take you from a clean sheet of 872 00:28:36,900 --> 00:28:40,080 paper to a running app on desktop mobile 873 00:28:38,279 --> 00:28:41,700 and web other GUI toolkits have 874 00:28:40,080 --> 00:28:43,260 tutorials as well if you want to go 875 00:28:41,700 --> 00:28:44,580 further token has its own docs the 876 00:28:43,260 --> 00:28:46,080 GitHub repo has lots of examples 877 00:28:44,580 --> 00:28:47,460 briefcase which is beware's tool for 878 00:28:46,080 --> 00:28:49,020 packaging apps and distribution is also 879 00:28:47,460 --> 00:28:50,940 well documented and isn't toga specific 880 00:28:49,020 --> 00:28:52,320 if you like what you've seen here and 881 00:28:50,940 --> 00:28:53,760 you'd like to support this work on toga 882 00:28:52,320 --> 00:28:55,200 and the beware project you can join the 883 00:28:53,760 --> 00:28:56,640 project as a financial member we also 884 00:28:55,200 --> 00:28:58,679 you can also back me on GitHub sponsors 885 00:28:56,640 --> 00:29:00,299 the income we use is raised to cover 886 00:28:58,679 --> 00:29:02,159 stickers hosting things like that as I 887 00:29:00,299 --> 00:29:04,140 said earlier I am paid by Anaconda to 888 00:29:02,159 --> 00:29:05,880 work on beware but the project itself is 889 00:29:04,140 --> 00:29:07,799 independently managed and financed so 890 00:29:05,880 --> 00:29:09,539 this funding is an important part of the 891 00:29:07,799 --> 00:29:10,919 project we've also got a Discord plus 892 00:29:09,539 --> 00:29:12,620 discussion forums and ticket trackers 893 00:29:10,919 --> 00:29:14,940 for the projects details on the website 894 00:29:12,620 --> 00:29:15,720 or if working kind is more your thing 895 00:29:14,940 --> 00:29:16,980 we're always looking for new 896 00:29:15,720 --> 00:29:18,120 contributors we have a long list of 897 00:29:16,980 --> 00:29:19,200 features we'd like to add we have 898 00:29:18,120 --> 00:29:20,820 challenge coins for people who 899 00:29:19,200 --> 00:29:22,740 contribute I will be here for the full 900 00:29:20,820 --> 00:29:24,000 Sprints I've got a long list of issues 901 00:29:22,740 --> 00:29:25,260 for first-time contributors and there's 902 00:29:24,000 --> 00:29:26,940 still plenty of low hanging fruit even 903 00:29:25,260 --> 00:29:29,340 if your own experience as as a python 904 00:29:26,940 --> 00:29:31,760 developer thank you all very much thank 905 00:29:29,340 --> 00:29:31,760 you very much 906 00:29:35,700 --> 00:29:38,820 thank you Russell thank you for a 907 00:29:37,559 --> 00:29:40,919 fabulous talk and thank you for your 908 00:29:38,820 --> 00:29:43,200 work on this uh um important talk about 909 00:29:40,919 --> 00:29:46,500 what's been declaring Gap in Python for 910 00:29:43,200 --> 00:29:50,760 a long time so are there any questions 911 00:29:46,500 --> 00:29:52,980 yes Eleanor Mike 912 00:29:50,760 --> 00:29:54,840 uh thanks Russ it was great talk really 913 00:29:52,980 --> 00:29:57,480 informative um I know from the testing 914 00:29:54,840 --> 00:30:00,360 slide you use the term dummy instead of 915 00:29:57,480 --> 00:30:03,360 mock was there something important uh no 916 00:30:00,360 --> 00:30:05,220 just a choice of words it is not really 917 00:30:03,360 --> 00:30:07,320 a mock in that it's not it's not 918 00:30:05,220 --> 00:30:10,740 pretending to be an underlying Library 919 00:30:07,320 --> 00:30:14,100 it it is a GUI toolkit it just doesn't 920 00:30:10,740 --> 00:30:16,260 draw anything and it's output it's GUI 921 00:30:14,100 --> 00:30:17,940 output so it's fundamentally like the 922 00:30:16,260 --> 00:30:20,240 same as a mock 923 00:30:17,940 --> 00:30:22,740 um maybe yeah 924 00:30:20,240 --> 00:30:24,659 I guess the difference the discrepant 925 00:30:22,740 --> 00:30:26,520 the difference I would draw is that it's 926 00:30:24,659 --> 00:30:27,960 not injecting itself in and pretending 927 00:30:26,520 --> 00:30:29,520 to be something that's not it is a 928 00:30:27,960 --> 00:30:31,620 legitimate Target in itself it's just 929 00:30:29,520 --> 00:30:33,480 not a useful Target 930 00:30:31,620 --> 00:30:35,399 we have an online question from Leo 931 00:30:33,480 --> 00:30:36,779 Gaggle asking what's the support of 932 00:30:35,399 --> 00:30:38,940 third-party widgets in togra 933 00:30:36,779 --> 00:30:40,559 specifically data visualization widgets 934 00:30:38,940 --> 00:30:43,559 um so 935 00:30:40,559 --> 00:30:45,059 it depends there is a matplotlib back 936 00:30:43,559 --> 00:30:46,799 end for example where like we've 937 00:30:45,059 --> 00:30:50,299 basically written a charting library 938 00:30:46,799 --> 00:30:53,399 that uses toga's native apis to drop in 939 00:30:50,299 --> 00:30:54,600 the issue is that those libraries like 940 00:30:53,399 --> 00:30:57,539 they need to draw something and they 941 00:30:54,600 --> 00:30:59,220 need to use a language to draw in there 942 00:30:57,539 --> 00:31:01,260 is almost no reason why those libraries 943 00:30:59,220 --> 00:31:02,399 couldn't be wrapped into a toga wrapper 944 00:31:01,260 --> 00:31:04,799 and it wouldn't actually be that much 945 00:31:02,399 --> 00:31:06,419 work like the matplotlib plugin is like 946 00:31:04,799 --> 00:31:07,799 a couple hundred lines of code and most 947 00:31:06,419 --> 00:31:09,320 of that is like transfer trying to 948 00:31:07,799 --> 00:31:11,340 transform what drawing a line 949 00:31:09,320 --> 00:31:13,860 matplotlid's drawing a line means in 950 00:31:11,340 --> 00:31:16,860 drawing a line in in toga if you've got 951 00:31:13,860 --> 00:31:20,100 a toolkit that exposes a native like on 952 00:31:16,860 --> 00:31:21,480 Macos an NS view wrapping that as a toga 953 00:31:20,100 --> 00:31:23,760 widget that you can just drop into a 954 00:31:21,480 --> 00:31:26,100 toga layout it's not that hard so it 955 00:31:23,760 --> 00:31:28,279 could be done are there any more 956 00:31:26,100 --> 00:31:28,279 questions 957 00:31:28,320 --> 00:31:33,480 yes 958 00:31:30,720 --> 00:31:36,720 microphone 959 00:31:33,480 --> 00:31:39,679 hi so I assume that the toga programs 960 00:31:36,720 --> 00:31:42,539 are compiled into uh whatever uh 961 00:31:39,679 --> 00:31:43,860 executable uh is necessary for the no 962 00:31:42,539 --> 00:31:45,899 but they're not they are interpreted at 963 00:31:43,860 --> 00:31:48,659 runtime so when when you ship to iOS for 964 00:31:45,899 --> 00:31:50,340 example what you get is a c python uh 965 00:31:48,659 --> 00:31:52,860 like straight up C python interpreter 966 00:31:50,340 --> 00:31:54,840 running as lib python uh there is a 967 00:31:52,860 --> 00:31:56,940 compiled component but it's basically a 968 00:31:54,840 --> 00:31:58,559 100 line bootstrap that starts a python 969 00:31:56,940 --> 00:32:00,120 interpreter that runs your code and it 970 00:31:58,559 --> 00:32:01,860 is being interpreted on the phone as 971 00:32:00,120 --> 00:32:03,960 python code at runtime oh because my 972 00:32:01,860 --> 00:32:06,120 question was going to be how reverse 973 00:32:03,960 --> 00:32:09,000 engineerable is is your code from your 974 00:32:06,120 --> 00:32:11,940 binary and so it's all there it's in a 975 00:32:09,000 --> 00:32:13,440 directory as python code so okay if you 976 00:32:11,940 --> 00:32:14,820 can get access to the IPA you could get 977 00:32:13,440 --> 00:32:16,799 the source code out like you then you 978 00:32:14,820 --> 00:32:18,659 fall into the usual app obsidication 979 00:32:16,799 --> 00:32:20,340 type stuff of only shipping the pycs and 980 00:32:18,659 --> 00:32:23,240 things thank you 981 00:32:20,340 --> 00:32:23,240 any more questions 982 00:32:23,580 --> 00:32:30,200 in time for one more 983 00:32:25,620 --> 00:32:30,200 occurring once going twice yes 984 00:32:31,380 --> 00:32:35,640 um he kind of mentioned how a lot of 985 00:32:33,120 --> 00:32:37,440 these GUI apps uh have a very similar 986 00:32:35,640 --> 00:32:39,720 type structure how difficult would it be 987 00:32:37,440 --> 00:32:41,820 to go from say a decanter to a gtk to a 988 00:32:39,720 --> 00:32:43,559 toga is it fairly transferable if you've 989 00:32:41,820 --> 00:32:45,960 written a GUI in one to go to the other 990 00:32:43,559 --> 00:32:48,299 uh depends how much you're leaning on 991 00:32:45,960 --> 00:32:50,279 the toolkit uh so like if you are using 992 00:32:48,299 --> 00:32:52,020 the vanilla I'm just putting widgets in 993 00:32:50,279 --> 00:32:54,779 buttons and things like blah blah blah 994 00:32:52,020 --> 00:32:56,340 the the top level surface apis very 995 00:32:54,779 --> 00:32:58,440 immediately transferable there are some 996 00:32:56,340 --> 00:33:00,539 local variations but not that hard if 997 00:32:58,440 --> 00:33:02,820 you are like a TK enter app where you 998 00:33:00,539 --> 00:33:04,620 are internally poking TK into 999 00:33:02,820 --> 00:33:07,080 configuration strings to make it do one 1000 00:33:04,620 --> 00:33:08,760 particular thing yeah that's not going 1001 00:33:07,080 --> 00:33:10,380 to transfer because you're programming 1002 00:33:08,760 --> 00:33:12,600 TK into there you're not programming a 1003 00:33:10,380 --> 00:33:14,279 GUI so you know it depends on the 1004 00:33:12,600 --> 00:33:16,559 problem but at least at the surface 1005 00:33:14,279 --> 00:33:19,260 level shouldn't be that hard like a a 1006 00:33:16,559 --> 00:33:20,760 tutorial how to build a QT app you could 1007 00:33:19,260 --> 00:33:22,860 probably translate it to a how to build 1008 00:33:20,760 --> 00:33:24,240 a toga app you know in in a couple of 1009 00:33:22,860 --> 00:33:25,740 hours it's just a matter of knowing what 1010 00:33:24,240 --> 00:33:27,419 what the spelling changes are 1011 00:33:25,740 --> 00:33:29,580 effectively beautiful thanks so much 1012 00:33:27,419 --> 00:33:32,100 thank you so much we have a small gift 1013 00:33:29,580 --> 00:33:34,940 uh to present to you Visa except that 1014 00:33:32,100 --> 00:33:34,940 thank you very much 1015 00:33:35,850 --> 00:33:40,000 [Applause]