# Python Tkinter Tutorial (Part 1): Getting Started, Elements, Layouts, and Events

## Метаданные

- **Канал:** Corey Schafer
- **YouTube:** https://www.youtube.com/watch?v=epDKamC-V-8
- **Дата:** 27.07.2024
- **Длительность:** 41:08
- **Просмотры:** 146,292
- **Источник:** https://ekstraktznaniy.ru/video/11725

## Описание

In this Python programming tutorial, we will learn how to get started with Tkinter, a GUI framework that is part of the Python Standard Library. We will cover everything from setting up your environment, adding elements to windows, configuring layouts, handling events, and more. By the end of this video, you'll have a solid foundation for building your own GUI applications with Tkinter. Let's get started...

The code from this video can be found at:
https://gist.github.com/558014ea68297f4fc89f46513260bb00

✅ Support My Channel Through Patreon:
https://www.patreon.com/coreyms

✅ Become a Channel Member:
https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g/join

✅ One-Time Contribution Through PayPal:
https://goo.gl/649HFY

✅ Cryptocurrency Donations:
Bitcoin Wallet - 3MPH8oY2EAgbLVy7RBMinwcBntggi7qeG3
Ethereum Wallet - 0x151649418616068fB46C3598083817101d3bCD33
Litecoin Wallet - MPvEBY5fxGkmPQgocfJbxP6EmTo5UUXMot

✅ Corey's Public Amazon Wishlist
http://a.co/inIyro1

✅ Equipment I U

## Транскрипт

### Segment 1 (00:00 - 05:00) []

hey there how's it going everybody in this video we're going to be learning how to create graphical user interfaces in Python using tkinter and tkinter is a popular package used for creating goys in Python and it's actually part of the standard Library so there shouldn't be anything additional that we need to install in order to start working with this now there are some other popular packages for creating user interfaces in Python and we'll take a look at some of those in the future and see why we might choose one over the other but in this video we're going to be getting started using tenter to create a basic application uh but first let me show you a quick example of something that we can build using tenter so I'm currently working on a personal application here let me pull this up and I built this using uh tenter and some databases in the background and what this is it's something to help me categorize uh credit card transactions and this is just a first version of this so there's a lot of uh changes that need to be made um but we can see here that it has everything that you'd expect from a typical guey application so we have text input Fields here uh radio buttons checkboxes um buttons for saving data we can even switch menus up here uh that shows me a list view of all of the categories that I currently have saved and things like that um so that's just a quick overview of something that we can build uh using tkinter and I'll actually do a separate video on writing those other applications from scratch uh start to finish uh but in this video I wanted to cover getting started with tkinter so we're just going to learn how to create a window uh learn about the basics of adding different widgets like buttons labels text fields and other common elements that are used in these types of application and we'll also learn about the different ways of positioning in order to lay out our widgets within the application exactly how we want and we'll also learn how to handle events like clicking buttons pressing on the keyboard and things like that so with that said let's go ahead and get started now I had mentioned that this is part of the standard library with python so there shouldn't be anything that we need to install uh using pip uh but in my case I'm using home brw version of python and it didn't connect everything in the background that needs to be connected so I actually had to go and install this additional Library through Homebrew then that is Brew install python dtk so even though it is in the standard library and there's nothing additional to install through pip uh on my specific system on Mac through Homebrew I did have to install this one additional package but now I'm going to go ahead and close that and bring this up so now let's jump in and start writing our first guey application now first let's run a basic test to make sure that everything is working as it should so to do this they have this uh helper function here to where we can just say import tenter as TK and then run tk. underscore test and if we run this then we can see that we get this popup window here and it gives us the latest version of tkinter uh or it tells us what version we're using and adds a button here that has some functionality to it and also a button to quit out of this now I'm going to be starting this tutorial with the assumption that what we did there works for you and that we can get started using tenter now if that test doesn't work for you then there are several things that could be going wrong uh in the background that are beyond the scope of this video so that I'm just not going to dive into here so again I'm going to start from the assumption that this script works for you so far up to this point okay so now we're ready to get started by writing a simple application so to do this we can initialize our main window and we will call this root so I'll say root is equal to and this is just tk. TK so if I was to run this now then we don't get any errors or anything like that down here but nothing actually popped up now something does actually happen here but it's just opening and closing the application too quickly for us to notice so in order for us to keep the window open we have to start the application's main Loop and this is also what allows us to listen for events like Mouse clicks and keyboard presses and things like that uh so we can start this Loop just by saying root Dot main Loop and if we run this then we can see that now we get this blank window with nothing in it uh which is what we should expect since we hadn't haven't added anything to our application yet so let's go ahead and do that now and add a simple button uh but first one simple addition that every guey should probably have is a simple title for the window that pops up so to set this right under where we're creating our root uh root we want to do above where we're starting

### Segment 2 (05:00 - 10:00) [5:00]

that main Loop we can just say root. tile and I'll just send this uh title to Simple app now if I run this then we can see here that we have a title of simple app on our window here now so that's good so now let's add some widgets and we'll start with a button now since tenter has evolved over the years there are a lot of different ways to do things now the goal in this video isn't to see how everything has evolved over time but to use the current best practices to get up and running so you may see other tutorials do something differently than how we're doing it here but that's okay uh all I can do is show you the most recent way of how I've learned to do things and if you do see someone doing it differently in the future then you can investigate that down the road when you come across it so let's go ahead and create our button so to add a button here I'm just going to say uh button is equal to tk. button and now we're going to pass in our root and we're passing in root here because this is going to be the parent window where our widget will be added and we don't have any others right now so let's go ahead and pass in root and we'll see some examples of some uh different parent Windows here in a little bit and now let's go ahead and give our button some text as well so I'll say text is equal to and we'll just say button one and now that this button is created we can add it to our window and we can do that using one of the geometry managers to specify how we want to add it to our window now we're mainly going to be using the grid layout in this series of videos since that seems to be the most flexible with most applications and it's also the layout mentioned in the tenter documentation as the more modern layout system so to add this button we can simply call the grid method on the button now you have to do this in order to get the button to show up in our window it can be an easy mistake to create a widget like we did here uh and wonder why it's not showing up only to later realize that we didn't use one of these geometry managers to explicitly add it to our window so to do this I'm just going to say button. grid and that will add it to our window if I save that and run it then we can see that now we have a very simple application here with a button that doesn't currently do anything now we're using the grid layout here and as you can probably guess from the name uh we can use this to lay out things in a grid with rows and columns so let's see what this looks like uh by adding a label before our button so to do this I'm going to close down what we have for now above our button here I'm going to create a new label and this is going to be tk. label and again we're going to pass in this root parent here and then let's go ahead and add some text to this as well I'll just call this label one now again I'll show you what this looks like if I don't add this using our uh grid system then we can see that we don't have a label here in our application so you always have to remember if you want something added then we can say uh label one. grid it uses that grid layout and now we have a label here above our button but one so by default it's stacking these on top of each other into a single column now we can specify exactly how we want these to be laid out by setting the rows and columns so let me close this and now where we're adding it to our grid here let's specifically say that we want this to be in row zero which this is a zero based index so that would be the first row and we'll also set the column to zero so the First Column as well and now let's also do this with our button so instead of row 0 column 0 I'm going to make this column one so now that should be in the second column now if I run this then we can see that now we only have a single row here and the label is in the First Column and the button is in the second column now I know that this beginning stuff can be a bit boring uh but we just have to build up this small stuff step by step in order to build our larger application okay so now that we've added a couple of widgets let's now add in some event handling so for example let's say that when our button is clicked we wanted to run a function within python so to do this let's first create a simple function here and I'll just call this oneclick and it's not going to take any parameters for now and I'm just going to have it print out testing and now to add this functionality to our button we can set the command parameter uh to this

### Segment 3 (10:00 - 15:00) [10:00]

function So within our button here when we are creating it I'm going to set the command equal to this onclick function now you want to be sure that you're setting it equal to the function itself and not the executed version of that function so we do not want uh the parenthesis here we want to pass this in uh without running it so now let's go ahead and run this and now if I click on our little button over here then we can see that down in our python script that it is printing out testing in our console so that is running that function as we'd expect now we can also use these functions to change values within the guey window itself so instead of printing something out within our python terminal uh what if instead we wanted to change our label when I clicked on the button so to do this instead of printing out testing uh all I want to do is I want to say label. config and we want to config the text of that label and we'll just say something like button clicked so now if I save this and run it make this a little larger here if I click on our button then we can see that now our label has changed to button clicked instead of label one so that worked now there's all kinds of different things that we can change with the config configuration of different widgets if you wanted to see what's available then you could either look these up online uh but for a quick print out we can simply call the config method within our script and print that out and this will return a dictionary with keys um so let's go ahead and see what keys are available uh with this label so after I create this label down here I'm just going to print out label. config and what we want to do here is just grab these keys so if I save this and I run it then we can see that we get some dictionary keys back here uh so we have active background active foreground um where is the text is down here so that's what we set when we clicked our function so there's all kinds of things that we can change here so for any widget if you want to see the possibilities uh then you can just run that there to get a list of all the keys that are available to you okay so now that we have the very basics down let's make a super simple form where we can uh have a place to insert text and we'll have a button that will add that text value to a list and also a list to hold all those values so connecting all that together will show us a bit more of how to handle certain events so to do this we'll add a couple of widgets that we haven't seen yet uh but the process is very similar to what we've already seen so first I'm going to go ahead and get uh rid of everything that we have here so far uh all except for our title uh rout and Main Loop so first let's keep everything a bit more organized by using a frame now a frame is basically just a container that allows us to hold different widgets and allows us to more easily organize our layout um let's create one of these now and then we'll look at why they're useful in just a bit so to create one I'm just going to say frame is equal to tk. frame and now we're going to pass in this root as the parent window and now we need to add this to our application as well so I'll just set this equal to row zero and column zero like we saw before let me fix this typo here and again like I said a frame is just a container for other widgets so if I was to run this now then we're not going to see anything uh we're not actually um adding anything to our window yet it's just a container so now that we have this frame added to our root window uh now we're actually going to add our widgets to this Frame instead of the root window itself and like I said before this will allow us to better organize our widgets in more complicated layouts and we'll see that in action and just a bit so now let's create uh a text entry within our frame so I'm just going to call this entry and this is going to be equal to text or tk. entry sorry and now instead of passing in root as our parent window we're going to pass in this Frame as our parent window so now it's going to be included in this Frame and this Frame is included in the root application going to have its own layout so even though we set this Frame equal to row zero and column zero within the root we're going to be starting over at zero when we add widgets to this Frame and if that doesn't make sense now then I think it'll make sense in just a second when we see how all this comes together so

### Segment 4 (15:00 - 20:00) [15:00]

now that we've added this entry to our frame we can specify that within that frame we want it to be on row zero and column zero of that frame so I'm just going to say entry. grid and we'll say the same thing here row zero column zero okay so now we have a text entry added to our frame and now let's put a button beside this text area that will add text from that field to a list so to do this I'm just going to call this entry button we'll set this equal to TK do button and the parent window that we want to use is the frame and the text I'm just going to put as ADD and again we're going to want to add this using the grid layout so I'm going to say entry button. grid row zero and instead of column zero I'll put this in column one so now we have our text entry and we have our button now let's put a list box below these that will hold all of the values that we add uh so to do this I'm just going to say textor list is equal to TK Dot and this will be a list box and again we're going to want to pass in that frame as our parent window and we're not going to add any more arguments there and for our grid layout on our text list let's put this on the second row so that would be Row one and column zero so now we've added a couple of things let me go ahead and save this and run it really quick and it looks like I possibly forgot to close down our last application sometimes you'll run into that when uh doing these gooey applications if you actually accidentally run one and then don't close it down then it could prevent you from uh running other ones in the future so let's make sure that that's closed down now I'll rerun it and we can see here that we have our text entry our add button and our text list so we can see that this isn't the best looking guy application um it's very basic and when I resize the window here it's not responsive when we resize our window uh but we'll fix all of that once we get the functionality working so what we want to be able to do is type something here into this text entry click on the add button and have it add it to this list box so to do this going to be sure to close out of our window here uh I'm going to add a function at the top of our script here uh called add to list so I'll just add that right up here so we'll call this add the list and it's not going to take in any arguments so first when we click this add button here uh button here uh what we're going to want to do is grab the text of this text entry so to do that we can say entry doget and we're going to want to set that equal to a variable so that we have that saved uh and now before we add the text value to the list let's make sure uh something was actually typed in uh we don't want it to add a bunch of blank lines if someone clicks the button multiple times so below here I can simply say if text and if there was text then we can add that to the end of our current list so to do this we can say text list and text list is down here it's what we called our list box we can say text list. insert and now we're going to use a uh special tenter constant that represents the end of the current content and a widget and that is tk. and then we can add in that text so again basically all we're saying here is when we run this add to list function we are uh getting the text that is in that entry uh if there is text there and it's not just a blank line then we can say text. insert at the end of the content of that widget and what we want to insert is that text and lastly uh in forms like this uh usually when they are submitted then it erases the original input from the field so that the user can continue entering additional values without manually clearing the form themselves so to do this we can simply just say entry. delete and we want to delete this from the beginning all the way to the end and again we're going to use this tk. as that special constant okay so this is all the functionality that want for when we click our button but

### Segment 5 (20:00 - 25:00) [20:00]

remember we need to tell our script to run this function when the button is clicked we saw this earlier and we can do this just by passing in this function as an argument to the command parameter so down here where we are creating our button I'm going to say that the command oops sorry is equal to and we want it to be equal to this add list function and again make sure that this function isn't executed you're just passing in the function name okay so let's see if we have the functionality that we're looking for I'll save this and run it and now let's test this out I'll say this click add is add a test and we can see that each time it added a new element to our list view here and each time it also um cleared out everything that we had in that text input area there okay so now another common thing that we might see in an application like this is keyboard events so we might want to uh make it so that the user can simply hit the inner key to add that text to our list instead of needing to manually click that button so to do this we can use the bind method on our entry widget and this will uh show us something about event handling that we haven't seen yet so let's go ahead and take a look so right below where we added our uh entry to our frame now I'm going to uh bind this entry and I'm going to bind this to a keyboard event and the first argument that we're going to uh add here is going to be the type of event that we want to act upon so for example we could be listening for button clicks a specific key pressed and things like that in this case we want to handle when the return key is pressed and the Syntax for that is simply Within These brackets here return and now that we have this uh return binded to an event now we need to specify what we want to happen when that event takes place now we already have a function that we've written for this uh but there is a caveat here um these bound events will automatically pass an event object as an argument to our call back function but our current function does not take any arguments so if we just pass that in as is then we're going to get an error so let me go ahead and do this really quick so I'll pass that in and let me quickly show you what this looks like if I run this then we can see everything works so far but if I add this in and hit enter then we're going to see here that we have an error because it passed an event argument to our function that does not currently take any arguments so there are a couple of different ways that we can handle this uh first we could simply change our function to accept an optional event object uh to do that we could just simply say event is equal to none by default and that would work now another thing that you'll see a lot of people using are Lambda functions for these callbacks a Lambda function is an anonymous function that doesn't have a name and is usually used for very short oneline functions so if I were to use a Lambda function then the Syntax for this uh would be Lambda and then the arguments that it's going to accept so I'll accept that event and now what we want to happen when this Anonymous function is ran um what we want to happen is we want to call this add to list function so that's another way you might see people do it um but I think it looks better the other way that we had it so I'm going to go ahead and put that back uh to the way it was so now if I save this and run it now in our application here uh we should have this uh keyboard functionality working so you can see I'm not clicking on the button so I'm just saying uh this is a test little out of order uh from how I typed it in but that's okay so there we go it says that uh all that is working so I'm going to go ahead and close set down okay so now that we've looked at handling different events and how to have different widgets interact with each other uh let's now take a look at some ways we can clean up our layout and make our applications look a bit better so first our application currently doesn't respond in any way when the window is resized and different elements aren't really lining up with each other uh within the window and this is because by default things that are added only take up the space that they need and that's it so let's make this look a

### Segment 6 (25:00 - 30:00) [25:00]

little better by having these widgets line up properly and also resize accordingly with our window so first if we uh look at our text entry area here or sorry not our text entry but our text list uh we can see that it only takes up one column which uh looks a little weird and that's because we have both the entry and the button widgets in the first row uh but only this one widget in the second row uh so to make this look better I'm going to tell this widget that it should expand two columns since there's only one element in this second row and that it should take up both of these columns so to do that I'm going to close down our window and down here where we have uh our adding this using our grid I'm just going to say column span is equal to two and now if I save this and run it then it should take up two columns but we can see that it's still a little strange here because uh now it's taking up two columns but uh it's centering it within those two columns so in order to get these widgets to take up the available space we can tell the widget to stick to certain sides of the window so to do this I'm going to close that down uh here I'm going to say sticky and for sticky I'm going to pass in ew and that stands for East and West so since we wanted this uh to stick to the sides the left and the right sides we're going to use East and West here so now if I save this and run it then we can see that this looks a lot better it's now taking up um all of the width that it needs to take up but it's still not responsive if we resize our window here so we can fix that next so in order to get this to be responsive we're going to need to configure the rows and Columns of our root window and our frame so to do this uh above the frame here let's go ahead and configure our row columns and our row rows I'm sorry our uh root columns and our root rows so what I'm going to say here is column configure and this is going to be for the First Column so an index of zero and I'm going to set an equ uh weight equal to 1 and I'm going to do the same thing for the row here as well so instead of column configure I'm going to have this be row configure and I'll have this be the first row weight equal to one so having the first row in column with a weight equal to one uh this makes it take up all the available space when it's resized and we'll look at different weights in just a bit but for now let's also configure our frame um now since our root window is able to expand we should now tell our frame to stick to all sides of that window when it's expanded so we're going to use that sticky parameter again but instead of just horizontal with East and West uh we want it to also be vertical with North and South so that it grows on all sides so frame here we're going to set the sticky here and we're going to have this be north south east and west and now we're just about done here uh what we want to do now is we want our frame to be able to expand as well so we have to configure those rows and columns just like we did with our root window but remember our frame has two rows of widgets and two columns uh we don't want all of these to expand evenly so for example it would look weird if our button expanded to be really big so our text entry and our list box are both in that uh first row uh so let's all ow those to expand uh only horizontally so I'll say frame do column configure and I'll set the First Column here with a weight equal to one so again our text entry is in that First Column uh our button is in the second column and our text list is in that First Column so the First Column is going to be able to expand and uh the second column is not so let me go ahead and run this now and if I resize this then we can see that this text input here is expanding to take up the additional space it's not sticking to the S yet our button is not expanding and our uh list box here is expanding horizontally for now so let me close that so first let's fix our list box so that it's uh growing vertically North and South as well so to do this I'll say a frame and we will do

### Segment 7 (30:00 - 35:00) [30:00]

a row configure and that text list is in the second row which is index of one and now instead of just expanding East and West let's also do north and south here as well and for our entry here it was expanding to take up the space but it wasn't sticking to the sides so let's also set a sticky here and we only want this to grow East and West we don't want it to grow vertically so now if we run this then let's take a look at what we did here so we can see that when we expand now that our text list is growing north south east and west and our text input entry here is only growing east and west and our button is staying um there to the side so everything is growing just as we specified and I think that looks uh a lot better than it did before so now let me go ahead and close this out okay so now we're going to take a look at one more thing uh before we finish up so just to show why using a frame is beneficial let's say that everything that we uh have currently is something that we would like replicated in different parts of our application or even in a new project since we added this to a frame it makes it easier to organize and reuse this set of widgets so for a contrived example let's just say that we wanted two different forms like this in our application that span two different columns in the main window so to do this let's make a copy and uh paste what we had before so what I'm going to do is I'm going to copy this Frame and all of the widgets that we have included here and I will paste these uh down below here and now this Frame instead of uh just calling frame I'm going to call this Frame two so I'm going to uh grab all of these here and I will rename these to frame two and I'm just going to leave these the same uh I should probably change those but really I just want to uh show the layout and kind of ignore the functionality for now so now we have this Frame two and we're creating a new entry and adding that to frame two a new butt button and a new text list and adding that to frame two as well so now that we've added this second frame since this frame has its own rows and columns we don't need to change anything about the layout of the widgets within the frame if we didn't have this in a frame and we wanted to add more widgets then we would have to come up here and say you know okay well this entry is in row one column one uh so I want this one to be in uh Row one column two and we'd have to do all this math that we just don't have to do uh now that we have this in a separate frame the only thing that we should need to do is uh specify where we want this new frame to be added so our old frame is up here on uh row 0o column zero and our new frame I'll just have this be in the second column so index of one now if I run this how we have it now then we can see that now we have uh two identical forms uh one in the first column one in the second column now if I resize this then we can see that these don't take up the same width when we resize now this is because of how we set up the weights earlier so let's change these to see exactly how these weights work so let me go back up here to the top where we set the uh weights on our root window so the reason our first column expands is because we set the column with a weight of one uh the second column doesn't have a weight by default so it only takes up the space that it needs and nothing more but if we wanted this to take up the same space as our other column then we could set this to one also uh by saying root column configure and we can set that column with a weight as one as well so now if I save this and run it then the should take up equal sizes on the left and the right since both of these columns are weighted the same so let me close this out so these weights are proportional to the weights of the other columns so for example let's say uh that the column on the left is meant to be more of a sidebar uh but we wanted to expand a little bit but not at the same rate as the column on the right uh so for that I could set the weight of the right column to be uh let's set it to three and then it would take up 75% of that

### Segment 8 (35:00 - 40:00) [35:00]

additional space uh than the column on the left so if I run this then we can see that now the column on the right has a much larger weight now you might notice that this doesn't look like it takes up 75% of the window and that's because it's taking up 75% of the additional space in this example uh so their original sizes don't factor into that size uh but this is a nice way to get our Windows to expand relative to the importance of what we're trying to highlight most within our uh gooey application so let me close that down now another extremely common thing that we might want to do for the layout uh is adding padding to our elements and this is super simple uh let's add padding to both of our frames to give it a bit more space between the edges of the main window so to do this on frame one here where we're adding it to our grid I'm simply going to add in a pad x equal to 5 and I'll add a pad y equal to 5 as well and we will put this onto our frame two also so let me go ahead and paste that in and now if I run this then we can see that we have a little bit of padding here between our main windows so it kind of gives a little bit of a visual separation okay and really quick before we finish this tutorial I want to show you a couple more tricks for helping our application look better among different platforms so one of those tips is to use themed widgets uh when they're available these are updated widgets that give a more native look across different platforms but not every widget has a themed version so for example in the code that we have here um the only widget that we're using that doesn't have a themed counterpart is the list box widget but let's use themed widgets on one of our frames to see if we can see a visual difference so to do this I'm going to import ttk which stands for themed tenter and this is also built into python so here at the top I'm going to say from tkinter import ttk and now let's use this on our first frame uh where it's applicable so instead of TK here for our frame I'm going to say ttk DF frame so hardly any change are made all we're doing is using theme keyer instead of the built-in one so I'm going to use this for our frame our entry Button as well and remember I said that this list box does not have a themed version so I'm only going to change those three so if I save that and run it then we can see that this doesn't look much different but these buttons should now look and behave more natively to the environment that we're on so we can see I'm on a Mac that the button here on our left frame is a bit different than the button here on the right and so as our text input it looks a little different as well I think they might even have different interactions for um how they look when you click on them and things like that we can see that this one it's a little bit more obvious than what it is over here so what theme tenter is trying to do here is just make this look a bit more native to the Mac that I'm currently running on uh so that's just a quick way to make our ations look a bit better across different platforms okay so what we've learned here so far should be enough of the basics to get you up and running with building your own guey applications but there's still a lot that we haven't covered so in future tutorials we'll take a look at more topics that we haven't touched here so we'll learn how to create these using classes how to have multiple windows adding images saving and opening files adding animations um showing or removing widgets based on want to condition and things like that there's a lot more that we can cover and like I mentioned at the beginning of the video I'll also show you how I built some of uh my personal guey apps that um I use on a regular basis like the uh credit card transaction one that I showed um also I built another one for game nights that simulates rolling Dice and tracks the roles I also have a guey application that I wrote for my father that reads in Excel files and uses Google Maps API to analyze specific coordinates from different columns and then Reaves those Excel files with that analyzed data uh so things like that are really good for guey applications and you can pass those off to people um who might not necessarily know how to run python but will your guey application so be on the lookout for those videos in the future but these fundamentals that we learned here should be enough to get you started with your own applications and experimenting with different widgets and layouts in order to solve particular problems that you might have um also in the future I would

### Segment 9 (40:00 - 41:00) [40:00]

like to take all of the tenter content and show how we can create these exact same applications using other goey Frameworks like pqt and Ki uh so be sure you're subscribe to keep up with those future releases but with that said I think that's going to do it for this video hopefully now you have a pretty good idea for how you can create some simple applications using tenter and how we can lay out our widgets and get them to interact with one another but if anyone has any questions about what we covered in this video then feel free to ask in the comment section below and I'll do my best to answer those and if you enjoy these tutorials and would like to support them then there are several ways you can do that the easiest way is to Simply like the video and give it a thumbs up also it's a huge help to share these videos with anyone who you think would find them useful and if you have the means you can contribute through patreon or YouTube and there are links to those pages in the description section below be sure to subscribe for future videos and thank you all for watching w
