So I have to admit that I initially definitely underestimated the seriousness of this QAnon phenomenon. I kind of just, like, didn't take it seriously because I looked at it as just one of those kooky conspiracy theories that people with too much time on their hands are obsessed with. But it's much more than that. Like, as more and more former QAnon members speak out, as their families share their stories about how this conspiracy theory tore their family apart. Like, this is something much more than I had anticipated. This is consuming people's lives. And I think that part of the reason why initially I didn't take it as seriously as it was is because the conspiracy theory itself, when compared to other conspiracy theories, in my opinion, is so out there, so easily disproven. I mean, the thing about QAnon is that you have one individual giving people very specific dates and saying this is going to happen on this date and then it doesn't happen. What Q says is going to happen never comes to fruition. So just like in and of itself, the conspiracy theory you'd think would be self-defeating. But still, folks are glued to it. They're consumed by it and they just are refusing to let it go. And even though Donald Trump is out of office and the theory should be null and void, that's not actually the case. Because as Right Wing Watch reports, there are still believers in QAnon who think that Trump is going to resume his role as the president on March 4th of 2021. Now, initially, before I learned more about this, I would have thought, okay, well, they're going to see that that's definitely not going to happen. So they're going to be forced to come to terms with reality and acknowledge that that's not going to happen.  But this is a cult and that's not the way that cults work. They're not just going to change their opinion based on new evidence. They're going to find a way to rationalize this and think, okay, well, maybe this isn't the right date. Maybe it was me. Maybe I misinterpreted what Q was saying and it's just going to go on and on. But I don't want to talk about like the actual conspiracy theory itself. What I do want to look at is how it has changed people's lives for the worse, how it has basically torn apart families. This is genuinely sad to me, but it's fascinating. I think we have to learn about this and take it seriously and try to help deprogram these people because this really is a threat to the social fabric. Quite frankly, it's sad. It's deeply sad. I've talked to folks who have family members who have become obsessed with QAnon and it's like they're different people. Like who they were before they became involved with QAnon was a completely different person. I want to play this clip from CNN. It features two individuals who talk about how their parents became obsessed with QAnon. And what they say here is really, really depressing. I lived just a few blocks south of the Capitol and so I started seeing people walking on the sidewalk, heading up to the Capitol with Trump flags and red hats. And I thought to myself, I wonder if my mom's here. I just thought to myself, let me check her YouTube. Loan hold choice. Right here at this rally. Look at this. I will never stop loving my parents. But it's this switch that flips in them when they're talking about what the latest Q drop means. They're not logical anymore. They're not understanding and often they're not kind. Not only does she really believe it, but it intersects in her mind with her religion. She has never put anything else on the pedestal equal to the Bible. And it really feels like that with this QAnon stuff. A conspiracy theory has taken over both these women's lives, but not by their choosing. I just want to have a mom who loves me or just pass that. They say their parents have been sucked into QAnon. My childhood was as perfect as any childhood could be. In the recent year or two years where this has become so much stronger within them, they've become completely different people. This woman is still desperately trying to save her relationship with her parents. It's why we've agreed to hide her identity. How did this all start with your parents? All through growing up. It was constantly, oh my gosh, like the Clintons. Oh my gosh, the Illuminati, things like that. But it all started really in the 2016 election cycle. Hillary Clinton and all of the Democrats are pedophilic and cannibalistic people that are trying to control the world. Things definitely heightened when I got to college. They would background search my professors. Hey, your professor, yeah, they're a registered Democrat.  When she did that, that said everything to me. That she was willing to put my wife's life in danger. And if she had called me up or texted me later that day or the next day and said, Hey, listen, I was at this rally. It got way out of hand. I'm really sorry. How are you guys? That would have changed everything, but it's been crickets. I haven't heard from her. We repeatedly reached out to Daniel's mother for comment and she did not respond. Have they changed their lifestyle in any way as a result of this? Well, last time I was there in my family's house, told me that they have a three-year supply of meat and freezer.  Are you concerned that they might blow their life savings on these freeze-dried foods and 300 pounds of meat? Not their life savings. My college tuition. That's hard. Whoever is the person that was running this Q account, what would you say to them if you could sit down and talk to them?  That is really interesting. And what I learned from this video is that the scale of QAnon, like the reach of it, was a lot more broad than I had anticipated. Like, I thought that basically the QAnon folks believed that this conspiracy just involved, like, national Democrats. But as that one woman said in the video, like, her parent did research on one of her professors and concluded that, oh, this person must also be part of that pedophile cannibal ring because they're a registered Democrat. Like, they genuinely believe that, like, the conspiracy is vast and it is far-reaching and a lot of people are in on it. And that's why they find it so compelling, I think, because this is something that's so big and they feel as if, like, they had this information that nobody else has and they don't just want to, like, educate themselves. I use educate, you know, very charitably here, but they want to inform others about this because they think they found something that's very serious and if there was, like, this group of politicians who were, like, worshiping the devil and eating children and eating others, human beings, I don't even understand that part. But if that were true, wouldn't that be, like, really shocking? So they go out of their way to try to convince others that, like, look, if you look for the conspiracy in this area, in this college, for example, you're going to find it because it is everywhere. They talk about how, like, it intersected with religion and, you know, her mom has never put anything on a pedestal equal to the Bible. Like, that's how serious they took QAnon. They've become completely different people. This is what I've heard as well. And I do want to share an article from the HuffPost. They did a really lengthy write-up that is fascinating. I'm not going to read this to you because it's too long, but I am going to link you to it because I think that this really gives you some insight into how people who were consumed by this conspiracy theory behaved. So children of QAnon conspiracy theorists explain how they're now trying to de-radicalize their boomer parents because they have been completely brainwashed by this conspiracy theory. So I'm going to go over a couple of examples. There's more. But there is a 19-year-old. His name is Sam. And he explains that his mom, even though she was never really political, she became consumed by QAnon. And part of the reason why is because even though she wasn't necessarily a political person, she was always a little bit more paranoid than usual. Like, she didn't fly on planes after 9-11. And as a result, that paranoia has led to her becoming obsessed with this QAnon conspiracy theory and supporting Donald Trump. There's a 28-year-old woman named Elena. And she says that her mom is intentionally going into debt because of QAnon. They believe that because of Q, that there's going to be some new financial system that emerges that will wipe away her debt. This is one of the elements of QAnon. They revived some old conspiracy about some new system.  And when you believe it that much, if you think that all of this is going to be wiped away, your debt, then why would you? It's a rational decision if you believe this. There's a 46-year-old woman named Kara. And she says that her mom literally just stopped taking care of herself because she became so obsessed. They didn't care about anything, but QAnon even stopped seeing her grandchildren. So this is absolutely destroying families. Destroying families because that individual, they become so consumed with this conspiracy theory that their identity and QAnon become inextricably linked to where they are QAnon and they're now trying to save members of their family who they believe should also adhere to the QAnon conspiracy theory. And there's a couple of screenshots that I want to share with you just to show the conversations that these folks had with their parents who were obsessed with QAnon. So this one is between Elena and her mom on Discord. Elena says, honestly, mom, I really thought you were smarter than this.   I'm highly intelligent. It makes me sad to see you be so brainwashed, but you will see. So Elena is then very clearly shocked saying brainwashed by, because I mean, obviously she's not the one who's brainwashed.  And then she says, it took me a long time of going through cognitive dissonance. I guess we just shouldn't talk anymore. I am tired of being hurt by you. Now, this is what Elena's mom is saying to Elena. You can tell just by the things she says, to even know what cognitive dissonance is.  This is a seemingly intelligent individual who knows about the way that our brains try to get us to not accept new information. If we have a belief system that's contradicted, the feelings that we feel are really unpleasant. Like we want to reaffirm what we already believe. But this person, Elena's mom, believes that it's actually Elena who doesn't believe in QAnon, who's the one that's been brainwashed, presumably by fake news and mainstream media. There's another text that I want to show you. This is between a man named Daniel and his mom. His mom is a two-time Obama supporter, and she voted for Donald Trump and became obsessed with QAnon. So he was texted this YouTube link to a QAnon thing. He says, this is literally fake news, and she says, that was quick. Thanks for checking it out. He says, please stop texting me your conspiracy propaganda. It's traumatizing enough to know you believe these lies and have been conned. These sources are 100% fake. Have a good night.  Have a good night. So there's this level of victimization that they feel. They feel as if they're oppressed. And on top of that, they aren't content to just believe the conspiracy theory. They're actually proselytizing. They're trying to share this conspiracy theory and get others to believe like it's a religion. It's a cult. It's honestly really shocking. And what we have to do is everything in our power to try to help these folks. But part of the point made in that HuffPost article, which was great, by the way, is that there isn't really like a support group. Like, this isn't something that psychologists have studied for hundreds of years. This is a new phenomenon. Like conspiracy theories aren't new.  And so really the one thing that folks have to comfort in if they have a loved one who became obsessed with QAnon is they've been going to subreddits and they're sharing, you know, QAnon casualties. That's one of them is sharing their stories. And that's really all that you can do is share tips with each other. I think that ultimately these people, they have to want to change, right? They have to have the desire to change. And you know, you can try to convince them. And I think that if anyone is going to convince them, it's going to be their loved ones. But this is something that is going to take a long time for these folks to overcome. I can't imagine QAnon existing decades from now, but you know, it might not exist in the same form. It could evolve, adapt to survive. I mean, this conspiracy theory is fucking, you think that by now it'd be over because Trump's out of office. He was supposed to declare martial law and arrest everyone on January 20th. And that didn't happen. But you know, the goalpost just keeps getting moved and folks keep believing it. Now, I think that January 20th was crucial because a lot of people were speaking out saying, okay, maybe I was duped. Was this all a lie? And that's really good. That's important. And we have to welcome these people back to society and reality. And we can't like shame them for abandoning their terrible beliefs and flawed beliefs. Like what we have to try to do is offer support, offer support to the folks who are trying to de-radicalize their parents who have become obsessed with QAnon and just try to help them. But I mean, the best that we can do is be understanding. And that's why I wanted to talk about this. I think that if we don't know what we're dealing with here, then it's really difficult to be understanding. But these are human beings and we have to try to come from a place of love and understanding and try to get them to apply, you know, a higher standard to things that they accept as the truth. Re-teach them or help them relearn how to evaluate evidence and facts and to use logic. It's tough. Look, with the internet, conspiracy theories aren't going to go away. But I think that we have to focus on ones that are really harmful. I think that QAnon is one that is particularly harmful because of the devastating impact that it has on families. Anti-vax conspiracy theories are very, very far-reaching and deeply harmful, especially during a pandemic since a vaccine is going to be the one thing that helps us end this pandemic. So there's a lot of conspiracy theories that we are going to have to combat as a society, how we do that. I don't know. But step number one is just learning and trying to understand what's happening here because we can't combat something that's harmful if we don't understand it. And that's where I'm trying to come in and help folks out. Thank you.


On Thursday, we found out that the U.S. GDP dropped a record 32.9 percent, the worst contraction ever. In the meantime, the president of the U.S. Trump toyed with the idea of delaying the U.S. election, something that even many of his supporters consider dangerous and a fascist move. The U.S. weekly jobless claims also rose for a second straight week, meanwhile the U.K. is worried about the second COVID-19 wave in Europe. Welcome to the Tick-Mill Update. I'm Kiana Daniel, the founder of the Investeva movement. Make sure to subscribe to the Tick-Mill YouTube channel and support us by liking and sharing this video with your forex trading friends. On Friday, we'll be watching out for GDP numbers from Spain, Italy and the Euro area, as well as the PCE price index from the U.S. Today, I'm looking at the dollar yen pair, which seems to be on a freefall towards the lows of March at 101, as investors dump the U.S. dollar and turn to safety in the Japanese yen. With Goldman Sachs also warning of the risk of further U.S.D. devaluation, we could expect the bears to win this game in the medium term. Now, do you think there is hope for the U.S. dollar recovery? Head over to the comment section and let me know. Of course, trading in the financial markets involves a risk of loss and you should only trade the money that you can afford to lose. If you like this video, give it a thumbs up and subscribe to the Tick-Mill YouTube channel. I'll get back to you with more updates next week.


All right, well, let's get going. Today, as you know, we'll be talking about GUIs in Python. So let's get started. Why do we need GUIs? We'll introduce you to some of the GUI programming paradigms that Python exposes us to. In particular, TKInter and then traits, which is something that's come out of, I guess, the n-thought people. It's part of the n-thought distribution. And then we'll talk a little bit about Matplotlib widgets. These are all three very different paradigms for interacting with data. So what are GUIs? I'm sure all of you intuit this already, but just to get it down. Graphical user interface, it's a visual, as opposed to command line or text-based interaction with the underlying architecture of your computing platform. And we most naturally think of this in terms of windows, as it's presented to us in two dimensions. And then our interactions, obviously, are not always typing. The one that we're all used to is, obviously, mouse movements and mouse clicks. And then, of course, if we want to tack onto that gestures, haptic touch, et cetera, that is everything that isn't text-based. And the idea is, obviously, to give us sort of an intuitive connection to the data and allow us to interact, perhaps in real time, with our own sort of simulations, for instance.  It's important to recognize that GUI idea has been around actually since the 30s, before there were computers. There was a very well-known article, as I just learned recently, like the last few hours. This great article in Ars Technica, which itself is very old from 2005, has a really nice, very long description of the history of the GUI. There were essentially sci-fi writers talking about how to augment mankind's interactions with large data. And then that inspired this guy, Douglas Engelbart, to essentially spend a good part of the 60s trying to create that kind of interaction. And he did some famous demo on live TV of a mouse and a keyboard, and moving the mouse pointer around on a graphical depiction of the data. This was obviously before Xerox and the Palo Alto Research, et cetera, and certainly before Windows and certainly before Apple. So this idea has been around for a long time, just interacting with the data in a textual way, obviously isn't the most intuitive. And then sort of jumping ahead from where we are now, there's obviously sort of the interaction with data, let's see, is this gonna work if I click, interaction with data on our machine, not even with touch, but just moving our hands around in space. Somebody has hacked the Connect, Microsoft Connect, to be able to basically do what Tom Cruise did in the Minority Report to go through a file system, he's scrolling around just moving his hands in the air, grabbing a file, pulling it down, and then he's gonna be able to make that larger, turn it around, et cetera. So this is what you'll be doing in two or three years from now, and it'll be called I Something and Apple will try to patent it, even though we've been talking about it ahead of time. So this is considered prior art, I guess. You Apple people in the future listening to this lecture. But sort of more to where we are right now, it's very clear, of course, that you can get a tremendous amount of information about what your code is doing in just basically a graphical representation of all the different, in this case, inputs to a simulation, perhaps you wanna change some numbers and you wanna see what the output is, you wanna interact with your code and you don't wanna do it all on the command line, perhaps even you wanna rotate things around in three dimensions. All of this makes sense to us intuitively, so I don't really have to tell you the power of this, but just to show you that it's used fairly widely. Then in systems control and actually visualizing not sort of simulations of the world, but actual feedback from the world and actually seeing how something is working, say in the context of a factory, it's nice to be able to visualize all the different parts of your actual hardware workflow and be able to, in some cases, take action and set triggers and things in a graphical way. It's much easier and obviously much better to intuit it in a graphical sense. Astronomers are quite used to this. Some of the biggest telescopes in the world use GUIs to take data. This is a graphical representation of all the things that we have access to on the Keck Telescope, which is a 10-meter telescope, in Hawaii using an instrument called LRIS, and what the observer gets to do is play around with all these different buttons. We don't actually get to move telescopes around because telescope operators are put in place to stop us from breaking the telescope, but we do get to interact with the instrument, so we can change angles of different gradings, we can change the different split wavelengths in our dichroics, we can put in different masks, we can open and close the door to this instrument, and we can do all this in a scripted way from the command line, but again, as something is changing, you might have stuff blinking and it just gives you sort of that visual clue of what's happening with your real-world hardware. This was written in Tickle-TK, I think about 18 years ago. We're still using it today, so a good lesson that the code that you write today will not be used by minority report type people in the future, it will be used by real people. This is my first Tickle-TK GUI that I wrote for a camera that I built as part of my PhD thesis back in the 90s, and it allowed us to take data simultaneously on two different cameras called J-CAM-0 and J-CAM-1.  And I could see when something was online, it was green and when it went off, it turned red, and so it allowed me to interact in a very complex way with this data-taking facility and then actually spit out sort of kind of responses and give us sort of real-time updates of what was going on. So this idea of GUIs for scientific programming is obviously very clear when you're trying to program whatever it is that you have in the sort of hardware side of things, and we talked just a little bit about simulations, but then of course, there's also the utility of GUIs in the context of teaching, which hopefully many of you will be doing. It's really great, you'll love it. So here is a JavaScript GUI that runs inside of a browser that allows you to change a couple of different properties of a binary orbit of two different stars, essentially dancing around each other, and you can essentially get a simulation. So I'll show you here of what we would wind up seeing on Earth in terms of different Doppler shifts from lines from those two different stars. So I can change the semi-major axis or the distance between those stars and make and update that change. I can change the eccentricity of the system, and I can update that change. In principle, you should be able to just slide these things back and forth and have those changes updated automatically, but it's pretty clear that interacting, now we know that there's physics happening under the hood, all I have to do is change these parameters instead of doing it on the command line, I can do it within a browser. Okay, so let's get into the anatomy of a GUI. So far, I haven't showed you anything that's Python-specific, although some of that stuff actually was written in Python, TK, Enter. The base construct of a GUI is the window, and we call that the root window, and so here we might want to call that root window for you to build a little calculator. Inside of that root window will be a bunch of different widgets. Some of those widgets may be display, so it's just showing you the value of what you just pressed, or they may be things like buttons, or maybe title bars. Everything within that window when you create it needs to basically get constructed and placed with respect to each other. They are instantiated, and they are associated with their parent window, so when I create a button I say this button has to belong to this window, and then I have to decide where I'm going to put that button with respect to everything else, and that's called a geometry manager. Okay, so let's see what happens and how I would actually lay this thing out. If you want to think about this conceptually, I've got sort of my display at the top, and that's this rectangle in purple, and then I've got all my sort of functions on the right-hand side, and then I've got my numbers on the left-hand side. If you want to break this down in the context of sort of high-level geometry, we really have three things, and inside of those three things, in the case of the one at the top, we just have one thing, and then inside of the one on the right, we've got eight things, and those are going to wind up being buttons, and all those buttons are going to have different meaning. When I click on one of those buttons with a mouse, or I bind perhaps a key press event to those specific buttons, then that's going to do something, and in this case, we intuit what that's going to be, you're basically going to be essentially doing math functions. So there are different notions of how you pack these different pieces of the puzzle into the overall window, and we'll go over how that happens within Python, but this sort of concept of a geometry is important, and there's different ways to do it. There's packing, gritting, and placing. Okay, so what do we have in Python? Well, the thing that's built into Python thankfully is something called TKInter. TKInter is a Python binding that actually wraps around an interpreter of the TK GUI APIs. That interpreter is sometimes called TCL, so you can essentially start a TCL interpreter just like you could a Python interpreter from the command line. I think the one that you probably all have on your laptop is called Wish, and then you can start typing TCL and TK commands. What Python does through TKInter, it exposes to you essentially TCL, but you're not actually programming directly in TCL. You're interacting through TCL to the TK toolkit. If that's a little confusing, hopefully it'll become more clear as time goes on. It's ported to all the platforms that Python runs on, so in particular, Windows, which is sometimes hard to get third-party window manager going, TKInter is the GUI of choice. There's also WX Python, which is an object-oriented wrapper around a set of APIs called WX Widgets. A lot of people use this. There's a lot of code base on this, but it is not built in. I think it comes with the end-thought distribution if I'm not mistaken. But if you're wondering about portability issues, WX Python may be a little bit worrisome. Then this thing called Traits, which is something that came out of the end-thought people themselves, is a different GUI paradigm, although itself isn't actually about GUIs. It's about creating objects and instantiating objects that have connections between each other, where it allows you essentially to strongly type Python. As many of you know, until you have decorators all over the place in your code that says that this variable has to be of type string, you can just keep on declaring variables and changing variables from strings to floats to whatever else you want. Traits allows you to basically declare that this variable is going to be a string, and it allows you to validate that, and then allows you to create connections between those variables, and then allows you to build essentially trivially GUIs around those complex variable objects. We'll see that towards the end of the class after the breakout session. But there's many more. There's the Python hooks to QuickTime, there's Python hooks to the GTK. If you are comfortable already with building GUIs because you've been doing it as part of your own work in one of these other platforms by all means, just use the Python hooks to that, and you'll be just fine. I don't want to overly proselytize TKInter or traits, which is what we'll focus on today, but do recognize and you can go to this FAQ that there are plenty of different paradigms out there. All of those paradigms have sort of four basics surrounding them when we're thinking about how to do good GUI programming. How many people have done GUI programming before? That's more than I thought, that's good. So I'm preaching to the choir. You know that you have to specify how the user interface is going to look, you have to specify what that user interface is going to do, and you have to connect the looking and the doing, and then finally you have to sit around and you have to wait for things to happen. So let's do our first GUI in Python. So from the command line, if you would, you can type from TKInter, it's a capital T import star that just puts everything into our namespace. As you know, that's not great coding style, but we're going to do it anyway. If you want, you can from the command line, type Python ghello.py, we're not going to be doing anything in the notebook today because we're explicitly working outside of the notebook. We're going to create standalone windows that are not part of the notebook. We then want to create a root window, and we do that just by calling TK, and then we're going to add a title to that root, and we're going to say, hello, question mark. Inside of that, we're going to make a label, and then we're going to pack it into that root. So the parlance for this is capital label, and then we have to give it the parent window, and that parent window is root, and we're going to give it some text. Is it me you're looking for? Then we're going to pack that, and we'll see more about the geometry later, but effectively we're packing that inside of the window, the root window, and then we have to actually make it happen and start waiting for something to happen. You do this by starting a main loop within that window, and so that loop is basically just an event loop that's just waiting for something to happen associated with that window. So when you do that and you run that from the command line, you should get something that pops up, and it's got the right title, and it's got the right text in there, and depending upon which platform you're on, you should see this stylized to the platform that you're used to. So if you're on Windows, you should see the normal Windows buttons, Mac, etc. as you can see here, and the way to open things up in Mac as you grab this corner. We haven't told the operating system to do any of that, and in fact, if you took this code as effectively as what's happening right now, you're taking this and putting this on different platforms with different window managers, you're going to get a different look and feel. But effectively what you're doing is you're saying to the window manager, make for me what you think is a window and put inside of it something that has a label. So this label doesn't have anything associated with it. I can't click on it. It's just a widget called label, which is basically for displaying text, and the window manager sort of obliges for you. Now you can tell it where you'd like to have it on the screen. There are lots of different things you can say with the total size of this window, you'd like it to be what the different laws should be for when I minimize it and all this. You can set all those things, but for the basic kind of hello world, this is essentially as basic as it gets. Instead of doing hello world, you see that we're invoking the spirit of Lionel Richie here. Lionel Richie needs to be part of, who codes to Lionel Richie by the way? Yeah, zero hands. That's what I thought. Good. Maybe do more coding to him. All right. So what is this event loop manager actually doing when you're actually saying, as we said before, main loop, you're starting something running. That is in charge of making the windows, resizing them, etc. It looks over the geometry and tries to obey all the rules of how you packed your different widgets inside of your window, and it's the thing that's watching over like this old lady looking outside of her window and yelling at the crazy kids downstairs when they're doing stuff they shouldn't be doing. It watches events and takes actions as appropriate, perhaps calls the police or throws their water bottle at them. So we'll do another one which is similar, and instead of just doing labels, we'll also create some buttons and we'll set actions to those buttons. Yes. So when you do it, well, how are you killing it? You're essentially destroying that route, and I think what happens for you with TK Inter is it winds up cleaning up that route. If you did root question mark, does it even know that that variable exists anymore? That behavior may not be consistent across platforms. If you say root.mainloop parentheses, that doesn't pop it back up.  I'm a little bit surprised about that, and I don't think that's true across all platforms. In general, you're not usually killing windows and then jumping out of the main loop. You could have multiple windows around and then you can essentially destroy, as it's called, one of the windows, but you don't kill the main loop. When you exit out of the main loop, you're essentially saying, I'm done with this whole thing, and there's probably a way to get that window back up if you really needed to. That's not the general workflow though. So if we just do all the same stuff we did before, but now we're actually going to make some buttons. First, I'm going to define two simple functions, which when called good, it will print on the command line good. When called bad, it'll print bad. Now I'm going to create two buttons, one I'll call B1, and that's again associated with the root window, and it's going to have a text that says yes, and it's going to be associated with a command which is basically a callback function called good. So when you click on yes, it's going to print good. Likewise, when you click on no, it will print bad. Hello, is it me you're looking for? Yes or no? Now I have to stick those buttons in, so I can create those buttons and they don't actually show up in my window. I actually have to now put them somewhere, and so I'm going to use the geometry packer, and I'm going to put this onto the left side, and I want to expand it out as much as I possibly can, and I'm going to fill it in the x direction. We'll see all these things later on. The sense in these geometry managers is that x is moving horizontally across the screen and y is moving vertically across the screen. Likewise, I'll do the same thing for the second button. That function, so the way that we call this button thing, the way we create this button, and we can do this after the fact, by the way. We can create a button, and then just like we wind up sort of decorating objects within Matplotlib where we say, oh, I've got, now I want to add a title to this thing, or now I want to change the color of this line, you can do all this stuff after the fact, but we're doing it right as we create it. Basically what you're doing is you're changing different attributes of this object called button. And again, Python is nice because it's making this look object oriented to you, even though TCL is not object oriented.  So why don't you give that a try and see if that works for you. I wanted to note that I have the end thought distribution that came out basically at the beginning, right at the beginning of the semester, and there's some issues sometimes when you're running these event loops within TKinter, that you get some weird statement about an error of not being able to get the right connection. Those are harmless errors, and I think that's been recently fixed. That's something that happened on Macs where it went from using, I think it was COCA to, what's the other window manager they use? Something else. What? Yeah, whatever. Aqua, aqua to coca, I don't know, coca to aqua. So don't worry about it if that pops up for you. Do you want me to run it here or are you guys okay demoing it for yourself? You good, okay? So you're clicking that button. Again, you're only sort of doing the very high level stuff, but TKinter is dealing with all of the even look and feel. Press your mouse button on the yes button and see what happens to the highlighting around the button. Right, you're seeing it's interacting, and you're interacting with it the way that you normally would. Okay, so let's talk about window, sorry, geometry managers. This geometry manager, basically the way we think about geometry managers in the context of a grid is we think about placing our widgets inside of a grid. And the grid is not something you pre-define. The grid basically is a concept that winds up expanding as you wind up adding more and more widgets. So when you first get going, you can say, put this widget at position zero, zero. And then forever more, you're gonna put stuff at one, zero, zero, one, whatever. You're gonna essentially address this grid like it was like an array. It will, that original widget that you had at zero, zero is gonna wind up staying there. But if I wind up creating something at 10, 10, and then I wind up starting my main loop, they're gonna not wind up being very far apart from each other. You're gonna wind up realizing that there's nothing in between. And this geometry manager is gonna just put them together because it's gonna say, oh, that's really what you meant to do. You wanna have all your widgets closed together. Now, you don't have to have it that way. You could create essentially empty labels that have a certain screen size and put those in between your two widgets that you set up. But when you first get going, and the idea with a grid manager is that you really know where you want everything to be with respect to each other. And you also sort of wanna know the relative sizes of these things. And we're doing this in abstract sense. A could be a label, it could be a button. It could be some text entry. It could be a checkbox. It could be all these concepts of the types of things you would do inside of a GUI. But for now, we're just keeping it abstract. Rows go down when we index it from the top left at zero, zero. So if I wanna put something in at A, that's gonna be at row zero, column zero. If I wanna put something at D, that's going to start at the top left corner. So I'm gonna index that at row zero, column three. But I can say I want that to span two columns and I want it to span two rows. So the X and Y sizes in this abstract sense are equal. And it's only when you start your main loop that it will pack everything together. So if I don't declare B, C, F, G, and I, but I declare A, E, H, and I use my grid manager to do that, and D, J, K, it'll just put all that stuff together as if this stuff in the middle didn't matter. So empty cells are ignored. There's no fixed grid size. That's essentially what the grid manager will work out for you and will be kind of your liaison to the underlying, the underlying window manager will say, I'd really like it because this was requested from the person that wrote this code for this whole root window to be of this size. And I really would like for this label to be of this size and say, you know, row zero, column zero. And it will try to faithfully deal with that for you. The thing to recognize is that when you're doing, when you're doing gridding, this widget, which again will do it in an abstract sense, will have some natural size inside of that grid. Now, the default is for that widget to essentially float at the center of that cell. But if I want to, I can stick that widget onto different parts of that cell. So as I wind up increasing my overall GUI size, my overall root window, I can basically say, consider the left side and the top side, the west or the north. So this is also kind of weird. X is increasing towards the east and Y is increasing towards the, Y is increasing towards the south. Anyway, so I declare this thing with, I want it to be sticky in the north and the west. Is that clear? So when I expand that out, so I could expand, if this was just basically one widget inside of one root window, that's sort of the simplest version of this, but it's the same sort of meaning when you're part of a big grid. When I expand that out, it's going to keep this thing stuck here and that thing stuck over there. If I stick on the east and the west and I wind up expanding my widget out, I wind up doing what you would naturally think where you wind up pulling this thing apart and stretching it apart. Maybe this is where GUI comes from. We can also set sort of the sense of how much weight these different cells will have when we're doing gridding so that when I expand and contract my entire root window, it's going to give more weight to different cells so we'll try more faithfully to keep those cells visible to you. If you give very low weight to some of the cells in your grid and then you start closing your window and making it smaller and smaller, the ones that have low weight will preferentially get removed and the ones that have high weight will wind up being shown. So if you're building one of these huge simulations and you wind up scrunching it down, you can actually set the minimum size of the root window. You could also set the maximum size of the root window. But as you get to your minimum size, perhaps nothing becomes as important as that one button that says run, right? Or maybe it's also showing you the results of the simulation. So you have to think about that if you really care about this stuff in detail. So if you run a file for the command line pythongrid.py, it should pop up something like this and you can see the different ways in which I've stylized each one of these labels. Some of these things are sunken. Some of those I don't actually stylize the outside of those. And you can just play around with shrinking, opening and closing these various things. And even if you want to, setting different weights to these different cells. This is just to give you a sense of what the grid manager is doing to give you a sense of what the stickies mean. You can see right here that some of these things are sticky in the east-west direction. Some of these things are gonna be sticky all the way around like the D. And the F and the G looks like F is sticky on the east direction and G is sticky on the west direction. And by doing that and putting them into adjacent columns in the same row, then I wind up basically having those two things stuck together. Shall I try that? You guys wanna run that too? Let's see here. Oh, they popped it up over here. Okay, so I can shrink this out. And you see that for the way that this manager is dealing with the different weights is it's putting, and there's that error, it's putting more weight on D, J and K. But it's more or less doing what you think it should be doing. If I really wanted I to be a fixed here, I could do that as well. But let's, it's not there, it's happening with the main loop. You can see basically how we do some colorization with this background. We can set different borders. You can set different reliefs as they're called. So ridges and grooves and sunken. You can put padding around them in the X direction. So you can have essentially a set amount of space and yet still do the sticky thing. So here is where I've done the gridding. So I've said, okay, I've got a label called A. Let's grid that and put that into column zero, row zero, and you set the different stickies and then you get what we got. And here I'm setting the different weights of the columns. Okay, any questions about that? I mean, this is really getting into the look and feel of your interaction with your GUI, but the GUI really is about stylization. So it's worth spending a little bit of time on this and understanding how this all works. Okay, so there's another geometry manager, which is not called grid, it's called PAC. And PAC is a little conceptually harder. The idea is that when you do a PAC, the ordering matters. So by the way, when I do that gridding, I could have gridded G before I gridded A and as long as I had the same calls, I would get exactly the same results. If I wind up packing, the order in which I wind up packing my widgets into my root window actually matter. So here you don't talk about east, west, north and south. You talk about sides. You talk about whether you're gonna pack this into the top or the bottom.  I'll pack something to the top. So that's basically saying, push this thing as far up to the top as you can within this window. Do another one, let's put another widget in and pack it as far up as you can to the top. And now I'll put another one in, so maybe I wanna have some sort of display and some sort of button and then at the very bottom, no matter what happens, I wanna have a quit button. There I might wanna say, pack it into the bottom. And when you do that, it will fill as faithfully as it can into the available space and now I have all this space. And now if I pack something to the left, it's going to do the best it can to basically put it over there. And as I change the sizes of the windows, these things are all gonna basically keep the same sense, but obviously the overall sizes of the actual widgets will wind up changing. So let's play a little bit around with the packing manager. So we'll create a button, which will be called quit. And you notice I haven't given a command. I could actually destroy the root window, that's one command, but I'm not gonna actually have this do anything. It can still be a button that does nothing and still stylized and still has text associated with it. And it's gonna be color or peach puff. I don't know why people use peach puff. Anyway, so then I'm gonna create something new, a new type of widget, which I haven't shown you yet. This is a check button. And it will also be associated with the root window. We'll do three of those things, A, B, and C. And then we'll create a label called what grade should I give you in this class? Hitting a little bit at home here. So and then I will wind up packing first the label and I'm gonna stick it to the top and I wanna make sure that it fills out in the X direction. So I've basically just completely grabbed all of the X, everything in the X direction. I'll share the implications of that in a minute. Okay, and now I want to pack something on the bottom and that's the quit button. And I'm gonna have that fill all the way out to the bottom. And then I'm gonna expand this thing out. What is it, A on the left? I wanna stick that on the left. And then likewise we'll do A, B, and C. And then we wind up getting something that looks like this. I think there must be, I know I'm missing some code because I didn't actually pack B and C in there. And I didn't show you that I'm running the event loop. But I think in pack.py we can take a look at that. That should be there. So there's pack.py. So we created a root and put a title on it. Yeah, and indeed, I didn't show you everything. There's a B and the C. And I kept, you notice I kept putting those other buttons or those other check buttons just onto the left. So the way in which we think about what's happening in the window, in the geometry manager sense. I don't think I have any chalk. So I'll just have to describe it. Ah, here we go, okay. So what I did at the start, so here's my root window. What I did is I put something at the top. And if I had said, put something onto, pack something onto the left. In principle, I could have taken some of this real estate here. But I said, I don't really want to have that happen. I want you to expand this out in the X direction. So I really grabbed everything at the top. And now if I had packed something on the left, it's gonna stick it over here or pack it on the right. But I did the same thing with the button here. This is the quit button. And then I said, oh, well, I don't really care exactly where all this stuff goes in the middle. I'll stick the A here, the B here, and the C here. And then I said, you do your thing and you decide where you want to put everything. And this expand equals one, which should actually be expand equals true. That's deciding if there's no, if nothing else is taken up when I actually say run event loop, what's the behavior in terms of filling up stuff at the end? And so it's doing what we think it should be doing. Okay, so here's a tiny exercise for you to do is take that pack.py code and change the name of it. And instead of packing things in, you can use exactly the same check buttons, but use the grid manager to get the same sort of look and feel. I'll give you a couple of minutes for that. So you're gonna say, button name dot grid, and then you're gonna have to give it some attributes. You kind of feel like we need some music to code with. This is relaxed coding. Peach Puff music, exactly, exactly. Do you have an app for that? Code that up using tkinter. The quicker you finish, the quicker we end this music. If you have questions, just shout them out. You should be approximately the same. You have to worry about your stickies and your column spans. Who's got it? Okay, I'll wait a minute. Yeah, work on the stickies. Well, first of all, in a grid sense, how many rows and how many columns should I have just by looking at this visually? Three by three, that's right. Okay, so anyone wanna talk about how they did their gridding? Well, where should I put that label E? What grade should I give you in the class? I put it at zero zero, and what else do I wind up saying about it? Yep, column span of three, sticky on, what did you say? Northeast and West. You could also do South too, if you wanted to basically really stick at the top and have this other stuff stick to it. That's getting into the subtlety of it, but certainly East and West and probably North. The one on the South, that's up to you. Where am I putting quit? That's row what? Row two column, also with a column span of three, good. And probably there you wanna do East, South and West for your sticky. And then it looks like A, B and C wanna be put in row one. And I wanna stick that at zero, so row one column zero, that's for A, B will be row one column one, et cetera. And probably the stickies I wanna have just on the North, or if I really wanted to, we could have them on East and West and also North. And don't worry so much about this white space, we got this from the packing where we packed these two up to the top and then we packed the quit button down there. If you really wanted to have this extra space and you wanted to ensure that you had extra space, you could create a label that was in the, I guess you'd have to move this down to the fourth row and you'd have to put something in the third row and have that have a column span and essentially be empty if you wanted to essentially ensure that space. Yeah, that's right, you would do that because you'd have empty stuff and then it would just essentially ignore those when it actually did the gritting. But that's a very, very important thing that we just hit upon, I wasn't planning on doing that. What happens when you decide, I really don't like where that widget is, I wanna add something, I wanna put it over there. The problem with the grid manager is that if you haven't laid everything out already and know exactly what it's gonna look like, chances are you're gonna have to go through and you're gonna actually have to change manually which row and which column something goes in. So now if I decide I really wanna put something in here that says D or no pass, I'd have to actually physically go and change this quit to be on the fourth row and then I'd have to add stuff to this third row where quit used to be. So this makes the iteration, the creation of the GUI a little bit painful but if you know exactly what it's gonna look like already, gritting is a pretty nice way of basically just ensuring that's where it goes. And then place, which we won't have time to talk about is a third geometry manager that has a very different paradigm. You're there essentially putting things in an X, Y location sense inside of your root window and you say put it at essentially pixel number this and you could have things like overlapping each other and all that. That's not very often used in TK Enter. So we haven't really done anything interesting yet other than just understand the layouts. I've introduced you to the check buttons. I've introduced you to buttons and labels but now it's interesting to start seeing what we can do. We've already seen actions that a widget can take in one, I think the only example I've shown so far is where we just print something out but obviously you could click on a button and the action could be go off and run a simulation that runs in a multi-core parallel environment and come back 10 days later and get some result. Doesn't have to be something that's trivial. It can be anything that Python can do that's considered a function. We can also like when we did the brushing example for your homework, when we did the Matplotlib week, you can also bind different events inside of different widgets or inside of even different root windows. So when I click the left button, I can catch that and I can take action when I do that or if I wanna bind another type of thing, like I wanna bind a key press, I can do that as well. There are other things that I can do. I can make sure that when a variable is changed, a certain special type of variable that I actually wind up defining. I can have a string variable, a boolean, a double, an int. I can say var equals string var and this comes from tkinter namespace and then I can set it to be hello and then I can set different types of callbacks on when that variable winds up changing in whatever way and by who. We'll see more of that in just a little bit. So let's do a watching variables example because now we start to get into some of the interesting sort of interconnected functionality of GUI programming. So we'll create a root window, we'll create a new variable which will be a string type variable and we'll create an entry and we're gonna create a new attribute of that entry. So this is a new type of widget, not a button, not a label, but something called entry and this is essentially a text entry and the variable will be declared to be my var so it's going to be of type string. I'm gonna pack that into the root and I'm now going to create a function which will say what the new variable is and this new variable, actually all these variables declared in this way will have various different methods. One will be set, the set method and the other will be get so I can get the value of that variable and then for us to do this we have to create a callback. So the callback function is named changing and I'm going to set a trace on that variable and when it's written, when it's changed because somebody's writing to it I want to essentially issue that callback and I'm going to print the name of that variable and inside of that variable, inside of that function, excuse me, the callback function I'm gonna print the value. So we can try this, it's events0.py of course I put it up on my other window here. So I set it to be by. Now you notice nothing happened when I just clicked inside of this but if I delete this I'm changing the value of that variable and now I can say hello. Every time I change it, that variable's being watched I call that callback function called changing and you notice I'm not violating anything by essentially typing it in a float. It can be anything at once because I'm saving it as a string. Now I think if I declared that as an int var and I started typing in letters I think basically the variable would get set to nothing. I don't think you actually throw an error but that's something you could wind up checking. Any questions about that? For some reason it's not getting me out of the main loop so I'll just delete. So that's interesting, it wasn't catching a keyboard interrupt inside of the main loop. You can actually bind a keyboard interrupt inside of the main loop if you want to take different actions like perhaps gracefully shut down or send you an email. So let's bind some events, something bind.py. So we'll create a callback and we have a little dictionary here and we're going to wind up basically getting a type of event. It'll become more clear when I actually show you what we're doing. Okay, so forget about the callback for just a second. I create a root window with just this TK and then creating something called a canvas which is yet another type of widget and a canvas does what you think a canvas should do. You should be able to paint inside of that and you could show text inside of it if you really want to. Usually what you wind up doing inside of a canvas is you wind up showing like an image or a movie inside of a canvas. I'll pack that in, I'll make sure that the focus of the mouse is set on that canvas. So that's what this focus underscore set does. And then I will bind a bunch of different callback functions to different types of events. So when I do a left mouse click, that's called the button one event. When I click enter, that'll be a different one. When I press a key, so that's anything that isn't an enter, isn't a button click, I'll wind up binding that. And you see what I'm doing, I'm actually just calling the same callback for all of them and then I'm taking different actions depending upon what type of event that was.  You actually just pass a pointer to the instance of that event. And that event has attributes like type and you can look up in the manual pages what a button press is of type four and enter is of type seven, a key is of type two. So it'll have some value associated with that. And then it's going to print out the location in the canvas in X and Y of where that happened. It's going to print out a character associated with that, a symbol associated with that and it'll actually tell me what the button number is. So let's, you can just try that out. You can try that at home too. So it's bind.py. So here's my canvas and I'm moving around inside of here. I'm not doing anything and then I'll click and you see I got button number. So that's button one. I think if I right click, I don't actually capture that. If I press the V button and I'm staying at the same location, then I wind up capturing that. If I move my mouse up to this corner over here, you can see that it's zero index from the top. I'll press the B button and I'm getting a key event down here. Now we'll press enter, right? So you can capture all this stuff inside of a canvas. If you want to, you could capture this inside of other types of widgets. It's most natural to capture these types of things inside of a canvas. But of course, if I click on a button, you're already going to take action on the clicking of that button. You usually wouldn't want to capture mouse movements, say around a button, but if you really wanted to, you could do something like that too. So this is nice. Like if I wanted to draw something now, you essentially could create very easily a draw function because I could just draw lines as this person is sort of dropping the mouse down, pressing the button, letting go. I could bind essentially a button one unclick and then you could just draw lines on the canvas. All right, so let's do something, let's see, we did binding events. Now let's actually do something slightly interesting where we're using a GUI. We'll watch a string variable and we're going to wait for that string variable to change. But what we're going to do is a quote of the day generator and I'll sort of show you what the code looks like and then we'll talk about what's actually happening. And this is only the code snippet for this file called events.py. When I say show quote, that is basically going to wind up being a callback from a button which we'll actually stylize and we'll say show quote. First of all, what it does is it's going to configure the button so that it is disabled so that I can't keep on clicking that button. What I'm then going to do is call something called update idle tasks. An update idle task basically says, if you've got a queue of things that you need to do and show the user, let's say I want to change the color of a label and I want to change it from peach puff to orange puff to yellow puff. If I do this line after line, eventually the window manager is going to say, oh, what's the last thing you actually wanted to do where I'm just sitting around waiting for something to happen? Oh, that was the yellow puff, I'll just show it that way. But if I really wanted to force it to update that screen, effectively this is the equivalent in Matplotlib of a draw where you're saying, draw what you have sort of remaining to do in your queue. In this case, I want to disable a button so that no one can press it again. But I don't want to wait for a long time. I want, as soon as somebody gets into the show quote, I want to disable that button and I want it to actually take action. I want to actually be disabled. I don't want anyone to be able to just keep on pressing a button. Then what I'm going to do is set the string variable to be whatever comes back from this call to urlllib and this is a url called ihartquotes.com and you can just get random quotes of the day and you can do this from the command line with a W get if you want to, we're going to do it inside of our little GUI. And then when it's done, we want to set this button back to being normal and then I'm going to update everything that's on the screen, that's inside of my window. So not just the button, but now I want to update what I'm going to wind up showing you in the center of this GUI. So the GUI is going to look like this. When I click on get quote, I want to gray that out so that I can't take action anymore. And you also see that we'll actually give some meaning to what this quit thing is. But I'm going to wind up watching this QT so it actually can happen asynchronously. Until QT changes, until I get an update, that's going to keep on having the same value as it had before. So when I click get quote, it doesn't erase QT, it doesn't erase that string on the screen, it will just wait until a new thing comes back. That value will change and then I'm going to say root update is going to change everything here. So let's give that a try. It was called events.py, right? Okay, so when I start off, that value of QT is just going to be click get quote. So let's try that. Ooh, that's a terrible one, let's change that. Okay, this is at least about code. Fortran will persist for some time probably for at least the next decade, that was probably said in the 60s. So you can see that we're updating what it is. We're essentially printing that out to the command line. Ooh, that was very poorly stylized. Probably need to make- It says what? It's about to disable the button. You want it to disable like it's supposed to be. Are you clicking it? No, if you just keep on clicking it, it's without you actually seeing it becoming undisabled, it's actually becoming enabled and it's essentially queuing up your clicks. But it's not running these things in succession. It is actually waiting until it becomes disabled. And you could set something where you wait for 10 seconds if you really wanted to before it becomes enabled again. I have no control over what is said here. That should be the disclaimer. Okay, so are there any questions about what's actually happening here? Does everyone see what we're doing? We're basically watching a string, we're changing that string and we're basically doing what you think should be happening instead of a GUI. We're allowing this thing to be enabled and disabled as that string is essentially being queried off of the web. Okay, so here's your breakout question. Create an instant calculator, sort of like what you get now from the Google search window where you're going to basically start typing and as soon as you type something that has meaning in a sort of evaluation sense from a math sense, you're going to wind up printing out the results. So here I start typing P and I got nothing up here and then as soon as I type Pi, this should appear instantly. And then if I keep on typing, I get nothing until I wind up getting a meaningful expression. So every time you change that variable, you're going to do an evaluation of that string. So you're going to watch that variable and just so you don't do anything malicious to yourself or to others, you can create a safe evaluation expression where you do an evaluation of whatever that string is, but you essentially turn off all the possible Python things you can do like OS system, RM star dot star and all that. And the only things that are available then are the variables associated with the math module. Okay, break out. Did you get a funny quote of the day? Yeah, I gotta be a little careful. So I think we'll get going. I think most of you got it already. If you wanna see how to do this in TKInter, I can show that later, but I wanna get moving on to traits and I'll actually show you this solution as implemented with sort of the traits paradigm. But effectively, I think most of you got it just so what you wanna do is you obviously wanna watch a variable associated with this text entry. So you're gonna define that as some string. You do an evaluation and you can wrap that in a tri-accept. Obviously if you have an error then you don't wanna do anything, but if you don't have an error, then you probably wanna update this text value associated with the label and there as I was saying before, you would instantiate that label and maybe call it L or my label and then you'd say text equals whatever you want it to say when you start and then inside of your callback function because you're now watching the string associated with this entry, you would do the evaluation and then you would say label name.configure text equals and that allows you to change the value of it. Okay, so I wanna move on to traits. As I said at the beginning, this is a project that came out of end thought and what traits allows you to do is sort of think about your data in an object-oriented way of course and now start creating sort of a complex set of variables that may all be related to each other. So now this is really thinking about object-oriented programming well and now GUI programming just sort of comes for free. Once I know the relationship between different types of objects and I've sort of made sure that every variable is used in the proper way that it should, then the creation of a GUI is nothing more than essentially creating a view of that object and instead of doing it on the command line you wind up doing it basically inside of a window. So traits adheres to this so-called MVC paradigm model view controller paradigm and it's basically what I just said. The model is what manages the data, the state and the internal logic of the application, the view formats the model into a graphical display that the user is allowed to interact with and the controller is really sort of managing the interaction between those two. It's sort of letting the user interact with the view of the data and then it's taking action inside of that model. That's a little abstract, we'll see how that actually works in just a bit. But the important thing is it allows you to think first about the data and then you start thinking about the visualization. So now you would think about your lambda expression and think about what is it that I'm really talking about? Well, I've got a label and I've got some entry and this is changing and this is gonna be of type string and I wanna now print that out. Now you start thinking about these things in terms of objects and all of that kind of event loop and lookup kind of happens for you in a nice elegant way. Some features of traits. One is initialization that all traits have default values. So here you would instantiate perhaps that label inside of the calculator and it would have a default starting value. Perhaps your calculator would have a default starting value. Validation, so every time you start typing inside of something you start changing a variable. It doesn't really take until you've got the right type. So if you declare this thing to be a float and then you type the letter A it's gonna say I don't know what you're doing here. Delegation, notification, stuff that we'll get into in just a little bit and then of course the visualization part of that. Okay, so this is thinking about modeling data in terms of classes fundamentally, okay?  Here's the code. We're just pulling a bunch of stuff from the namespace and we're going to, sorry for those that hated our use of bears in the early days of this course and in the bootcamp but we're doing it again. So we're gonna create a class which will be a subclass of an object called has traits and then we're going to declare a bunch of different attributes of this bear. It will have a name and that will be of type string. So it forces us to have a type string. It will have a color associated with it. It will have a weight. It will have a location which is going to be an array type. There'll be a data directory associated with that bear perhaps maybe where its images live and now when I instantiate a bear, I can give it a name, I can give it a weight, I can give it a location and you notice upon instantiation I haven't told it what color it's going to be and where the data directory is gonna be associated with that object but it still winds up having meaning because I have the concept of a default. And then the way where instead of starting the event loop, what you say is configure traits and that's starting the event loop. It's connecting all the different types of classes together because as we'll wind up seeing they can be related to each other. So let's try that. Where's my mouse? It's called traits one, right? Of course, where did that throw it? Here it is. So there, I essentially created a GUI and I didn't say anything about how these GUIs were gonna look but pretty, you know, obviously I could wind up stylizing how this is gonna look but the nice thing is because all these have a sense of what type of object those are, what type of property color now has a GUI associated with it where I can see, I can set my bear to purple, I can open up a nice little representation of my directory tree and I can change that of course. Favorite food, I can enumerate the possibilities of what favorite food are allowed. You can eat a Palo Alto and I can change the name to whatever I want. I can change the weight, et cetera, okay? We haven't actually done anything with that but what you should recognize of course is that as I change it in the GUI I'm actually changing it inside of the instance of that object. And traits exposes to you a bunch of high level types and the color type is pretty cool because it knows how to stylize itself and when you have a GUI now I can just select essentially from a color wheel and I didn't actually have a color where I had a drop down menu. You could tell it when you show a GUI to me that's associated with this color show me now something that looks like a color wheel and it has a sense of what a color wheel is. So there's lots of different things in here. If you're gonna get into this you're gonna wind up getting familiar with all these different predefined types and of course you can define your own type as well. So we can do what we did before or something like our calculator where we'll do a very simple version of that where we have something called underscore variable underscore change that's a special method of one of these has traits objects. So now I'm gonna create a very simple counter it's gonna be a value and it's gonna have an integer and won't have any default it'll be a type integer and I'm going to have something called add one which will be a type button and a button has a couple different things you can do to it. The obvious one is when you click on it and traits way of saying click on it is fired. So if I say add one that's the name of my variable actually underscore add one underscore fired every time I click on add one it's going to do this. It's going to add to itself this value the value attribute it's gonna add one. I have to create a view. So when I actually show this thing I want it to do some things I wanna show I wanna show the value I wanna show a different item perhaps I wanna play around with the labeling so I actually don't wanna say that this thing here is called add one which is what it would say. So I can turn off the label for the add one item you'll play around with how to do all this stuff but it should be pretty clear what's happening. So now I'll just configure traits on that counter and it's gonna get going. So that's called button.py Here it is oops here it is. So add one add one I'm clicking. If I set this to be 12 I clicked. Oh and notice what happened when it was a string I actually got this thing to stylize to look red I didn't have to tell it to do that but if I have a plus b it's clearly unhappy with that and if I click on here it's just doing something to it it doesn't have any meaning when I say a plus b. Did it convert it to true? I don't think so. So that's a complex I could have declared this thing to be a complex variable but I declared it to be an int so it doesn't really have meaning. 1.0 that is not a type int so it's doing some sort of checking of type for me and that's something that we're not really used to in Python but it's doing all that stuff naturally for you. So if I say add one to that saying two what if I said 3.0 and I clicked add one to that four. So it's keeping a sense of that variable but it's pointing to you that it's not actually of type int it's of type float but it's doing what Python likes to do when you're going between floats and ints it does the best it can. Any questions about that? So you notice we're not explicitly watching a variable we're just saying that different types of things like a button have a concept of firing and that gives you your natural callback and notice I had to create a special view inside of that bear so that I didn't actually show you the label for the add underscore one button. Okay so let's do what we did in TKinter but let's do it inside of traits. So I'll create an expression which will be the thing inside of my box there that I'm gonna wind up typing in. I'm gonna have a result which I'm gonna have as default type an expression. When the expression changes I'm gonna be past the old value and a new value and so that's actually how that's called and I'm gonna try to evaluate the new one if not I'm gonna do nothing. I'm not gonna, well yeah I guess I'll show you that. It doesn't stylize very well because I didn't create a view and I didn't tell it how to behave. It's called iCalc so here it is here and I can type one plus one plus one j plus e and you notice I can't actually open this thing up I can't actually make it any bigger. Maybe I don't wanna say the word expression maybe I wanna change this around. What I have to do is create a different or a specialized view of how I want this to be exposed to me whenever I do a configure traits. But you see the functionality is there in just a few lines, fewer lines than you needed before. Okay so view item allows us to create a stylized view of the model and this is the visualization part. So here's this complicated view but it sort of makes sense. We've got some width, we decide it's resizable. It's got a little padding associated with it. I give it a result. I decide which order I want it to be in. I can create a title on there. I can say that the buttons are called okay. You know I can basically create whatever view I want and the cool thing is I can create multiple views so that I can have it in different contexts the same object being displayed in different ways. In this case I'm gonna configure traits with a certain view and that view is be called in this case view one. So we can try that. So that looks really nice. Okay, what happens when I click okay? Ah, it closed for me gracefully. Here's a demonstration of something called delegation which is part of traits. So here I have a simple version of my bear and it is inheriting everything that the has traits object knows about. So I'll give it a first name. I'll give it a wait, I'll give it a float. Of course I could define other methods on this bear just because it's of a subclass of this thing called has traits. If I wanted to we could do all the same stuff that we did when we were talking about the size of the bear population. But here I wind up having a couple of, for every instance I wind up having a couple of different attributes. And favorite food is gonna be an enumerated thing, honey, turkey, Palo Alto and in the default will be honey. And now I can create a subclass of the bear object and this will be apparent. So this will be the sort of sense of what a parent bear is. And I'm going to have a last name and when that last name is changed, so this is the equivalent of what we saw in TK Inter where we were watching a string and then we were setting a watch on that string. Now we're going to see what happens when we change it. The parent's last name changed to something and it used to be the other thing. And then I'm gonna push that out to the command line. And now I'm gonna create a concept of a a daughter or son, a cub. So that'll be a subclass of bear. And we'll have a last name. And here's what's interesting. I can now delegate the last name to whatever its father is. So if I declare a variable called father, that father better be of type bear and it will then grab the last name of the bear. So it's the equivalent of when we did the underscore underscore in it inside of a subclass and then you sort of run the underscore underscore in it of a base class and then you grabbed all the attributes from there. Effectively that's what we're doing except these things are intimately connected. So if I change one, I automatically update the other. There'll be a father and a mother and it'll be of instance of type parent. So I'll create Yogi, which will be of type parent. First name will be Yogi, a weight of something. Last name Morgan. Sally, last name is Clime. And then they're going to make a cub which will have the first name of Saki and Oskie, excuse me, I don't want to think of it. I really would like to have Saki when this is over. That is, yeah, maybe a Freudian slip, maybe. Anyway, so father is Yogi and mother is Sally. And so, oops, so all that stuff should make sense and we can try to run traits too and see what happens. Where is it? So it just basically dumped out because I didn't have inside of traits too this actual configure. So that's everything I showed you already, but I want to show Oskie and now I've got my edit properties. I didn't do any special view here so it's showing to me in any order I want. And look, father is of type father. If I click on that, I wind up getting the properties of the father and it's got honey so I can change that. And I can change the last name of the father to be my last name. And what you can see is that Oskie's last name is now Bloom because I changed the father's name and Oskie's last name has been delegated to whatever the father's name is. That's obviously a contrived example but now I can look at the mother and let me try to change that. Fernando's last name and you notice nothing changed. Oh, last name. Oh, I don't know why that changed to Perez. That shouldn't have done that. Oh no, it didn't change here. It was doing the callback but it didn't actually change the last name of Oskie. So that's that kind of intimate connection across classes. This is the sense of delegation and you now have the sense of inheritance being also something that you can play with at the GUI level and not just at the sort of command line level. Another thing you might wanna do, of course, is not just deal with numbers and deal with pointers to other classes of objects but maybe you actually wanna do something of interest where you're playing with data and you'd love to be able to stylize a plot and you'd like to play around with, say, the zoom of the plot and the color scheme and all the things that you would naturally wind up doing in Matplotlib. Unfortunately, it's a little bit contrived to be able to use Matplotlib within side of a traits GUI. There are ways to do it and on the next slide, I'll show you how to do it but it's still obviously very powerful if you're gonna be doing a very complicated traits model and then you wanna actually do something with Matplotlib at the same time, right? You'd like to be able to interact with those plots. So you have to import something called MPL Figure Editor which is part of traits and you have to create some sort of object which has as its base class that has traits object and you create something which is a variable of type instance and then you have to create a figure associated with that and then you have to create a special view of that figure and you have to give a sense in the view of what the editor is and that editor comes from your MPL Figure Editor and then you can run all that stuff. So that should actually wind up working and I think I have an example of that in the folder that I gave you but as you already know, Matplotlib and this is sort of the last third of what I was gonna tell you about today has its own widgets. So if you import matplotlib.widgets as WG and then you type WG.tab, you will see that there's a lot of the concepts of what we've talked about today already built inside of matplotlib and you can start essentially creating directly and natively within matplotlib the types of widgets that you might wanna be interacting with if indeed what you're looking at is playing with some sort of figure. So again, you can do it within traits and that's not unreasonable and then you can bring in all the functionality of matplotlibs and yet still use a nice traits view but matplotlib itself, as long as you don't need all the special things traits can do, can obviously be very powerful. So here you actually wanna be able to interact with say the amplitude and the frequency of the sine wave. Perhaps you wanna change the color of that and the widgets give you access to that. So let's take a look at the slider demo. So that's the sort of typical matplotlib markup that you see sort of gray backgrounds. You see when I move my cursor in here I get all the functionality. Now I can zoom in on this thing, can go back but interestingly, I can change the amplitude and the frequency. These red lines are the default so I can set the concept of a default and if I reset, it goes back to its original and change the line color, et cetera. And then you can obviously decide where you wanna stick all these different widgets. So this is pretty powerful if you're gonna be writing something that's gonna allow you to interact with your data in a way that we'd like to be interacting with our GUI data, right? It's like we'd like to be not just showing something, going on the command line, changing one value, seeing what happens. You'd like to be able to do this in quasi real time. So matplotlib is great if you're just dealing with data traits is sort of the next thing you would wanna think about if you're also gonna be dealing with lots of objects and connections between objects. And TKinter is really kind of a basic functionality of GUIs within Python. When you, I believe when you pull in that Canvas editor, it is doing the proper event handling for you but I don't know the details of how you get access to like a button press within it but I'm pretty sure you can declare traits, attributes inside of a class that are the results of having pressed a button. But whether you can say underscore button press underscore fired, I'm not exactly sure if that will work. That is what I'm talking about being able to do. I mean, you could really clue something if you wanted to and basically create that window and sort of figure out a way to coerce like the result of the creation of a GIF or PNG from having run matplotlib. And every time you press go, you fire matplotlib and then you're just showing the result of the PNG. That would be the clues you way to do it but to have it interact directly with it, you have to use that template that I showed you on the previous slide. I should also say about matplotlib is that there has been some work although I don't know how much in earnest and who's doing it to use not as the back engine, you're like coca or WX or AGG, your windows managers instead using as a back engine, HTML5. So that when you're actually interacting with matplotlib, you're doing it inside of a browser. And so you could be pressing buttons inside of a browser and that's been created for you, essentially using HTML5. That's been around since 0.99-ish. I don't know how far along that's getting. It's not been put in, but I think it even comes with the most recent end thought distribution. Well, maybe they ship it, they ship it. Yeah. But it is currently the description that you gave of the Fuji way getting into the thing. It fires up its own server, right? It's essentially creating a web server. That's right. It sends it over the events. It captures the events on the web browser and then sends them over, re-renders the whole SVG and sends it back to you. There's a work underway to make that more interactive. But right now it's that sort of the Fuji way. Like it's not this lightning fast. You'd think SVG is local to my browser. No, it only sends you a fully rendered SVG thing. And when you pan, it'll send you a full new rendered SVG thing right now. There's people working on something to move that like this. Cool. All right, so unless there's any other questions, I'll give you your homework. Okay, so your homework. I don't know what's a six. Should be eight. Well, anyway. Is it homework six? Really? Aren't we in week eight? Yes, but we start with a zero. We start with a zero and we have one.  Okay, homework six. Use traits and the traits UI to create a GUI application that consists of a search box, a text display, an image display and a series of buttons. The application will accept search strings in the search box and then run an internet image search. The first return image from the search will be downloaded. The image URL displayed in the text display field and the actual image will be displayed in the image display field. Buttons will provide the user the ability to basically essentially run the search but then do manipulations on the current image inside of the display like I could blur or rotate. And so what we're asking you to do is provide at least three unique and interesting image manipulation functions. So those of you that did some of this stuff in the XML RPC or obviously many of you who solved the or attempted to solve the image classification problem, you're already very familiar with different types of interesting things you can do on images. So you can use any image search you want. Yahoo has a pretty nice search module and you can decide how you wanna do display but effectively what we're looking for is a GUI that looks something like this where if I queried money Python and humor I'd wind up getting back some image. It will display that image and then I can blur it, sharpen it, smooth it, do edge, whatever manipulation on all this stuff. Yes. Like what? Sure. I'd like for you to get used to doing it with traits because I think that's a really nice model but if you're already used to using PyQT, that's fine. Yeah, yeah. Any other questions? Okay.


What's going on guys welcome back to Bitcoin Daily for another video in today's video. We have a special one for you guys. So we've had a lot of requests about trading strategies. You guys want to know you know what different type of trading strategies there are and what we use and stuff like that. So even though trading strategies are always changed and they're always you know dependent on the scenario and situation today we have a special one. It's a momentum trading strategy. This type of strategy is very good for when you're following the trend and when the prices are going in an uptrend or downtrend doesn't matter you just need the momentum and go with the trend. So that's what we're going to cover today. Please guys make sure to hit that subscribe button. We're at 2100 we passed that today we want to hit 2200 by the end of this week and continue up and that's pretty much it guys make sure to like the video hit the notification bell and let's jump into it. Trading can be highly volatile. So it is very important to have an excellent strategy to secure consistent profits. Most beginners have many options most which are adopted from forex and stock trading but momentum trading is one of the best trading styles thus far for volatile markets. That's why we use them so much in crypto. This strategy reflects expression trend is your friend perfectly well. While there is no strategy without risk momentum trading gives traders more control and fewer potential failure points. Momentum trading is a strategy or trading style in which traders assess the strength of a current trend to open position in its direction. The primary rationale behind momentum traders moves is that if there is enough force driving a price move then it will continue to move in the same direction for a while. The first task of a momentum trader whether you're trading crypto or stocks is to assess a trend's strength before opening a position. The strategy involves analysis of three key metrics to understand the momentum of a trend. These are volume volatility and time frame. The volume suggests how many traders have opened positions in the direction of the trend in a given period based on a number of assets traded. However sometimes the trading volume can be manipulated by wells that means financially capable traders can buy or sell large amounts of the asset. Volatility is another important aspect of the price that is closely monitored by momentum traders. They prefer volatile markets like stock option trading or cryptocurrencies for the short-term ups and downs. Finally momentum trading is closely related to the time frame selected by a trader since a trend is making sense only within a specific time frame. For example, Bitcoin can increase on the hourly chart but that may be a temporary swing as it declines. If the trend on several time frames coincides then this considers as a stronger momentum. So we're going to go over some of the best momentum indicators to find these trades right? So for momentum traders technical analysis is critical because it helps traders define the forex stock or crypto market trend and analyze its momentum. Here are some essential technical indicators to find momentum with greater precision. Average Directional Index The average directional index or ADX is probably the simplest and most popular indicator to determine the strength of a trend. The purpose of ADX is to evaluate momentum for better judgment in an asset. Basically ADX is an oscillator and its calculations are sophisticated but effective for price trend analysis. ADX reflects the strength of a price trend on a graph which goes between 0 and 100. When ADX dips below 30 it suggests that the price is moving sideways. As ADX breaks above 30 it means that the price is trending. Ultimately the higher the ADX goes the stronger is the trend in a particular direction. However make sure that you know that the ADX doesn't show whether a trend is bullish or bearish as the indicator is focusing on momentum alone. Moving averages are the oldest and most common technical indicators out there. They have been popular for decades to analyze all kinds of assets and it's for good reason. Moving averages cut the price action's noise to smooth the volatility that confuses traders and displays the general trend. Traders use moving averages to calculate the average of price movement over a given period. For momentum traders moving averages are important because it can show whether a trend continues its direction or tends to go sideways. It is visually apparent as the moving averages follow the price action. Traders would generally use two moving averages with different periods. When the shorter moving average crosses the longer moving average then the existing trend may be reversing and momentum traders will be interested in closing out positions. The relative strength index is one of the most popular oscillators which acts as a momentum indicator. It calculates the size and magnitude of the latest price changes. The RSI line is on a separated chart below the price action and goes between 0 and 100. If the RSI goes below 30 it shows an oversold level suggesting that the current downtrend might reverse. On the flip side, if the RSI goes above 70 the market enters an overbought level meaning that the current uptrend is losing momentum and might gradually turn into a downtrend or move horizontally. Thus momentum traders should be on alert whenever the RSI is above 70 or below 30 as the bullish or bearish sentiment is reaching over saturation and the trend is changing. Moving average convergence divergence or MACD is a bit more sophisticated. It behaves like both a momentum and trend following indicator. The MACD merges two exponential moving averages and its results is calculated by subtracting the 26th period EMA from the 12th period EMA. However the two lines displayed on the MACD chart are not the two EMAs used by the indicator instead one of the lines is the MACD line and another one is the signal line which can determine changes in price momentum and provide buy or sell signals. There is also a histogram which represents the difference between the MACD line and the signal line. When the two lines depart from each other momentum is considered more substantial and traders can rest assured that the current trend would continue. There are many momentum strategies that involve several technical indicators or chart patterns to provide buy or sell signals. Here I will show you one of the simplest and still reliable strategies that you can test on your own trading platform. For this you will need to set an exponential moving average with period 19 and the ADX indicator. Here are the buy conditions. Check whether the ADX is at 30 or above. It shows that the price is trending. Next check whether the EMA is pointing upwards. It suggests an uptrend. Next wait for a candlestick to close fully above the EMA and enter a long position. Then you can exit the market manually when the price crosses the EMA. Don't forget to check the volume from time to time. Higher volumes suggest strong momentum thus signaling a more accurate indicator to buy. On the contrary if you intend to go short with this strategy you should meet the following conditions. First check whether the ADX is at 30 or above. Note that the ADX shows a trend strength rather than the direction. Next check whether the EMA is pointing downwards because it suggests a bearish trend. And last enter the market after the first candlestick that closes below the EMA with its full body and shadows. Momentum trading is an excellent style for beginners because of its simplicity. Here are some benefits of this approach. Momentum trading can be profitable since it follows a trend. It can work with any timeframe and suits both day traders and swing traders. Momentum trading allows cryptocurrency traders to leverage high volatility. Obviously there is no trading strategy without its risk. Momentum trading is very dependent on the trend and sometimes traders can be taken by surprise by unexpected trend reversals. It's important to note that technical analysis indicators cannot always anticipate reversals since they analyze past prices. Also prices can move up and down without any prior clues due to unexpected events. So you should always consider those things. To succeed with momentum trading you have to apply proper risk management techniques and stick to the strategy that you choose. All in all momentum trading is one of those universal strategies that are suitable for both beginners and professionals. Momentum trading is backed by a lot of technical indicators that were designed precisely to determine the strength of a trend. The great thing about this style is that it can do a great job with any timeframe higher than 30 minutes. This strategy can be implemented by both day traders and swing traders. Thanks for watching guys. Peace and love.


Here you are teaching a face-to-face class with all your materials. Then you get the message. You have to put your course on Canvas to teach your class remotely.  Instead watch the videos in this playlist. You'll learn about modules, the basic building block of Canvas, pages, which are pages of information for your students, assignments, things you want your students to turn in for grading, and quizzes. At the end of this playlist you'll be ready to start putting your materials on Canvas. Let's begin.