Now coming back to our main.py
our previous program had a label,
a button and an entry, and it was relatively simple.
So I'm going to head back to this main.py file
where we've got only three widgets so that I can show you how we can define the
layout and positioning of each of our widgets.
Firstly, I've reconfigured the file a little bit. So I've moved the button
_clicked function to the top,
and I've made sure that each of the pack methods are at the very end of each
widget. That way we'll be able to work with it quite easily. Now,
as I mentioned before, tkinter has a whole bunch of different layout
managers that define how to position each of the widgets in your GUI program.
Now there's three that you should know about, pack, place and grid.
Now, firstly,
we've already seen pack and all that pack does is it basically packs each of the
widgets next to each other in a vaguely logical format.
And by default, pack
will always start from the top and then pack every other widget just below the
previous one. As I mentioned,
you can change this by adding a side parameter and you can change it to for
example, side = left.
And if you change this for all of the packs,
then it's going to pack everything starting from the left edge of the program
like this. And you can change that to bottom or right as well.
But the problem with pack is that it's actually quite difficult to specify a
precise position. So for example,
if you wanted this label to be a little bit up and then this button a little bit
down and this entry all the way to the right. It's very,
very complicated to do that using pack.
And that's why there's not just a single layout manager,
but there's lots of others. So let's take a look at the next one,
which is called place. Place is all about precise positioning.
So when you place something,
you can provide a X and Y value. So for example,
I can say my label.place, and then I can say, well,
the X value should equal 0 and the Y value should equal 0.
And this just places that label at the top left corner.
Now it's important to remember that if a widget gets created
but it doesn't have any layout specified it using pack, place or grid,
then it won't be shown as you can see here,
we've only got the label showing up. Now that we've placed our label to the top
left corner, we can try placing it in somewhere else.
So let's move it a little bit along the X axis.
So let's say place it on a (100, 0)
That moves it to the right a bit more, and if we want to move it down
we can change the Y position.
So now it's down at the bottom and then the X is 100. Now,
remember we've defined the width and height. So the width is 500 pixels,
the height is 300 pixels and anywhere along that screen,
you can define a X and Y value for a particular widget to place it at that
precise position.
The downside of place on the other hand is the fact that it is so specific and
we have to work out in our head the coordinate and where to put each widget.
It simple enough if you've only got three widgets like we have here,
but if you have a hundred or fifty,
then that becomes quickly a bit of a nightmare to manage the precise coordinates
of each widget.
So in addition to pack and place, there's also a final layout manager
which also happens to be my favorite one,
which is the grid. And the grid is a really simple concept.
It imagines that your entire program is a grid and you can divide it into any
number of columns and rows that you want to.
So just as a reminder, the rows are the ones that go along the horizontal and
the columns are the ones that go along the vertical.
If I remove my place and instead I use my grid,
I could say my_label.grid,
and then I can provide a column and a row number.
So let's say I'm going to put it at the first column and the first row.
So then starts from zero so that we could say column = 0, row =
0. And you can see that it gets placed in the top left corner.
Now the grid system is relative to other components.
So even if I change this column to, I dunno, five and the row to five,
you can see that it doesn't actually change the layout because there is no
widget in column four, three, two or one.
So it's still the first one in the grid.
So the easiest way of working with the grid
is starting with the things that you want it to be at the top left,
defining a starting column and rows, zero, zero,
and then for the next and subsequent widgets to just keep going through it and
define its position on the grid. For example,
if I wanted the button to be on column one and row one
and then I want my entry
which is called input to be on the grid in column two and row two,
now if you run this,
you can see it's now been laid out along our grid.
And this is effectively what it looks like.
Our label is in column zero row
zero, button in column one row
one and entry in column two row two.
This is one of the easiest ways of visualizing and creating the layout for your
tkinter programs. And it's really flexible
and it's really easy to imagine and understand.
So this is always my preferred way of working with the layout for
tkinter. Just a word of warning though.
You can't mix up grid and pack in the same program.
So for example, if I wanted my label and my button to be defined by the grid
but then I decide to use the pack method for my final entry,
then you can see I actually get a error when I run my code. It says,
cannot use geometry manager pack
which already has slaves managed by grid.
So these two are incompatible with each other.
You basically have to choose one or the other.
And often I will choose grid because it's just more flexible and more easy to
understand. So now here comes a challenge for you.
I want you to change the code that we've already written so that we end up with
this layout. So we've already got a label, a button and an entry.
I want you to add a new button and it should be positioned like this.
Have a think about how you might solve this challenge using the grid system that
you learned about just now. Pause the video and complete the challenge.
All right. So the first thing you notice is that the label is still at column
zero row zero, button is still at row one column one,
but this new button is now at row zero column two.
So let's go ahead and create it.
Now I'm just going to create a new button and I'm not going to worry about its
command or any of that.
I'll give it a piece of text just so that we can identify it and I'll call it
new button.
But then the most important thing is how we lay out this new button.
So I'm going to use the grid system and I'm going to give it a column of two
because it is zero, one, two,
the third column from the left and then row is going to be zero.
Now, when I run this code though, you'll notice something a little bit odd.
Why is the entry below the button? Because in our example,
the entry is actually over on the right of this new button in a new column.
By putting this new button in between the old button and the entry, we've
actually changed the positioning of that entry on the grid.
So we've actually had to move it along into the next column.
So to do that,
we have to change the grid of our entry instead of having column two,
to make it column three, just so that its on the right of this new button.
And now when I run it, this has the exact layout that we wanted
and we've now learned a little bit about how we can precisely position our
widgets in our program using the pack, place, and grid layout managers.
The very last thing I want to show you with relation to layout and design of our
GUI programs is how to add a little bit of padding around components.
The easiest way to add padding is actually to directly modify the widgets.
So for example,
if I wanted a bit of padding around all of the elements in my window,
so basically added around the edge of the window,
then I could simply say window.config and I can change the padding in the X
axis and the padding in the Y axis,
so padx and pady.
So now if I run this program as it is,
you can see that there's now more space being added around all four edges of our
program. Now I can make this a lot more extreme.
So let's say I add the padx to be 100 and the pady to be 200,
you can see just how much padding we've now added.
And this just means that you add more space around your program and it makes
things easier to see and looks a little bit nicer.
If you want to add padding around a specific widget not just the entire window,
then you can do the same with that widget. So we could get hold of my label and
again
using config to change the padx and the pady. So let's add, maybe I dunno,
50 pixels of padding in the X and in the Y.
Now you can see that around that label
there's a whole lot of space so that it pushes everything else away and actually
makes the entire program window a lot bigger.
So this is just a way for you to be able to add space around your widgets so
that they're not all crushed together
and it helps you with your layout and your design.