1
00:00:00,570 --> 00:00:03,480
Now coming back to our main.py

2
00:00:03,780 --> 00:00:07,170
our previous program had a label,

3
00:00:07,200 --> 00:00:10,320
a button and an entry, and it was relatively simple.

4
00:00:10,740 --> 00:00:13,560
So I'm going to head back to this main.py file

5
00:00:13,830 --> 00:00:18,570
where we've got only three widgets so that I can show you how we can define the

6
00:00:18,570 --> 00:00:22,350
layout and positioning of each of our widgets.

7
00:00:23,460 --> 00:00:28,380
Firstly, I've reconfigured the file a little bit. So I've moved the button

8
00:00:28,380 --> 00:00:30,060
_clicked function to the top,

9
00:00:30,540 --> 00:00:35,540
and I've made sure that each of the pack methods are at the very end of each

10
00:00:37,110 --> 00:00:41,760
widget. That way we'll be able to work with it quite easily. Now,

11
00:00:41,760 --> 00:00:45,930
as I mentioned before, tkinter has a whole bunch of different layout

12
00:00:45,930 --> 00:00:50,930
managers that define how to position each of the widgets in your GUI program.

13
00:00:52,440 --> 00:00:56,340
Now there's three that you should know about, pack, place and grid.

14
00:00:57,270 --> 00:00:58,080
Now, firstly,

15
00:00:58,080 --> 00:01:03,080
we've already seen pack and all that pack does is it basically packs each of the

16
00:01:04,319 --> 00:01:08,340
widgets next to each other in a vaguely logical format.

17
00:01:08,970 --> 00:01:10,470
And by default, pack

18
00:01:10,470 --> 00:01:15,470
will always start from the top and then pack every other widget just below the

19
00:01:15,600 --> 00:01:18,360
previous one. As I mentioned,

20
00:01:18,390 --> 00:01:23,390
you can change this by adding a side parameter and you can change it to for

21
00:01:24,840 --> 00:01:27,360
example, side = left.

22
00:01:27,900 --> 00:01:31,200
And if you change this for all of the packs,

23
00:01:31,260 --> 00:01:36,090
then it's going to pack everything starting from the left edge of the program

24
00:01:36,390 --> 00:01:40,890
like this. And you can change that to bottom or right as well.

25
00:01:41,550 --> 00:01:46,550
But the problem with pack is that it's actually quite difficult to specify a

26
00:01:46,800 --> 00:01:49,080
precise position. So for example,

27
00:01:49,080 --> 00:01:53,370
if you wanted this label to be a little bit up and then this button a little bit

28
00:01:53,370 --> 00:01:57,240
down and this entry all the way to the right. It's very,

29
00:01:57,240 --> 00:01:59,910
very complicated to do that using pack.

30
00:02:00,390 --> 00:02:03,360
And that's why there's not just a single layout manager,

31
00:02:03,390 --> 00:02:06,870
but there's lots of others. So let's take a look at the next one,

32
00:02:06,870 --> 00:02:11,760
which is called place. Place is all about precise positioning.

33
00:02:12,300 --> 00:02:14,430
So when you place something,

34
00:02:14,910 --> 00:02:18,870
you can provide a X and Y value. So for example,

35
00:02:18,870 --> 00:02:22,890
I can say my label.place, and then I can say, well,

36
00:02:22,890 --> 00:02:27,300
the X value should equal 0 and the Y value should equal 0.

37
00:02:27,720 --> 00:02:31,500
And this just places that label at the top left corner.

38
00:02:32,160 --> 00:02:36,270
Now it's important to remember that if a widget gets created

39
00:02:36,570 --> 00:02:41,010
but it doesn't have any layout specified it using pack, place or grid,

40
00:02:41,250 --> 00:02:43,920
then it won't be shown as you can see here,

41
00:02:43,920 --> 00:02:48,920
we've only got the label showing up. Now that we've placed our label to the top

42
00:02:49,200 --> 00:02:52,110
left corner, we can try placing it in somewhere else.

43
00:02:52,380 --> 00:02:55,260
So let's move it a little bit along the X axis.

44
00:02:55,290 --> 00:02:58,350
So let's say place it on a (100, 0)

45
00:02:58,800 --> 00:03:02,320
That moves it to the right a bit more, and if we want to move it down

46
00:03:02,320 --> 00:03:04,570
we can change the Y position.

47
00:03:04,930 --> 00:03:09,310
So now it's down at the bottom and then the X is 100. Now,

48
00:03:09,310 --> 00:03:13,750
remember we've defined the width and height. So the width is 500 pixels,

49
00:03:13,750 --> 00:03:17,440
the height is 300 pixels and anywhere along that screen,

50
00:03:17,710 --> 00:03:22,710
you can define a X and Y value for a particular widget to place it at that

51
00:03:23,380 --> 00:03:24,760
precise position.

52
00:03:25,630 --> 00:03:30,630
The downside of place on the other hand is the fact that it is so specific and

53
00:03:31,540 --> 00:03:36,010
we have to work out in our head the coordinate and where to put each widget.

54
00:03:36,400 --> 00:03:39,820
It simple enough if you've only got three widgets like we have here,

55
00:03:40,120 --> 00:03:42,490
but if you have a hundred or fifty,

56
00:03:42,490 --> 00:03:46,870
then that becomes quickly a bit of a nightmare to manage the precise coordinates

57
00:03:46,930 --> 00:03:47,920
of each widget.

58
00:03:48,910 --> 00:03:53,260
So in addition to pack and place, there's also a final layout manager

59
00:03:53,350 --> 00:03:55,300
which also happens to be my favorite one,

60
00:03:55,660 --> 00:04:00,160
which is the grid. And the grid is a really simple concept.

61
00:04:00,490 --> 00:04:05,490
It imagines that your entire program is a grid and you can divide it into any

62
00:04:06,640 --> 00:04:08,770
number of columns and rows that you want to.

63
00:04:09,190 --> 00:04:13,660
So just as a reminder, the rows are the ones that go along the horizontal and

64
00:04:13,660 --> 00:04:16,450
the columns are the ones that go along the vertical.

65
00:04:17,529 --> 00:04:22,330
If I remove my place and instead I use my grid,

66
00:04:22,630 --> 00:04:25,330
I could say my_label.grid,

67
00:04:25,660 --> 00:04:29,680
and then I can provide a column and a row number.

68
00:04:29,710 --> 00:04:34,120
So let's say I'm going to put it at the first column and the first row.

69
00:04:34,150 --> 00:04:38,320
So then starts from zero so that we could say column = 0, row =

70
00:04:38,320 --> 00:04:42,010
0. And you can see that it gets placed in the top left corner.

71
00:04:42,760 --> 00:04:47,170
Now the grid system is relative to other components.

72
00:04:47,410 --> 00:04:52,240
So even if I change this column to, I dunno, five and the row to five,

73
00:04:52,600 --> 00:04:55,750
you can see that it doesn't actually change the layout because there is no

74
00:04:55,750 --> 00:04:58,990
widget in column four, three, two or one.

75
00:04:59,200 --> 00:05:01,900
So it's still the first one in the grid.

76
00:05:03,340 --> 00:05:05,620
So the easiest way of working with the grid

77
00:05:05,650 --> 00:05:08,830
is starting with the things that you want it to be at the top left,

78
00:05:09,070 --> 00:05:12,010
defining a starting column and rows, zero, zero,

79
00:05:12,370 --> 00:05:17,320
and then for the next and subsequent widgets to just keep going through it and

80
00:05:17,350 --> 00:05:20,530
define its position on the grid. For example,

81
00:05:20,530 --> 00:05:25,530
if I wanted the button to be on column one and row one

82
00:05:27,970 --> 00:05:30,580
and then I want my entry

83
00:05:30,610 --> 00:05:35,610
which is called input to be on the grid in column two and row two,

84
00:05:39,580 --> 00:05:41,230
now if you run this,

85
00:05:41,260 --> 00:05:45,100
you can see it's now been laid out along our grid.

86
00:05:45,640 --> 00:05:48,040
And this is effectively what it looks like.

87
00:05:48,400 --> 00:05:51,160
Our label is in column zero row

88
00:05:51,160 --> 00:05:53,590
zero, button in column one row

89
00:05:53,590 --> 00:05:56,860
one and entry in column two row two.

90
00:05:58,130 --> 00:06:03,130
This is one of the easiest ways of visualizing and creating the layout for your

91
00:06:03,920 --> 00:06:07,400
tkinter programs. And it's really flexible

92
00:06:07,490 --> 00:06:10,850
and it's really easy to imagine and understand.

93
00:06:11,120 --> 00:06:16,100
So this is always my preferred way of working with the layout for 

94
00:06:16,130 --> 00:06:18,620
tkinter. Just a word of warning though.

95
00:06:18,650 --> 00:06:23,650
You can't mix up grid and pack in the same program.

96
00:06:23,990 --> 00:06:28,760
So for example, if I wanted my label and my button to be defined by the grid

97
00:06:29,060 --> 00:06:34,060
but then I decide to use the pack method for my final entry,

98
00:06:35,600 --> 00:06:40,580
then you can see I actually get a error when I run my code. It says,

99
00:06:40,610 --> 00:06:43,070
cannot use geometry manager pack

100
00:06:43,250 --> 00:06:45,980
which already has slaves managed by grid.

101
00:06:46,370 --> 00:06:49,010
So these two are incompatible with each other. 

102
00:06:49,010 --> 00:06:51,890
You basically have to choose one or the other.

103
00:06:52,490 --> 00:06:57,050
And often I will choose grid because it's just more flexible and more easy to

104
00:06:57,050 --> 00:07:00,980
understand. So now here comes a challenge for you.

105
00:07:01,520 --> 00:07:06,380
I want you to change the code that we've already written so that we end up with

106
00:07:06,380 --> 00:07:10,310
this layout. So we've already got a label, a button and an entry.

107
00:07:10,670 --> 00:07:15,650
I want you to add a new button and it should be positioned like this.

108
00:07:15,950 --> 00:07:19,940
Have a think about how you might solve this challenge using the grid system that

109
00:07:19,940 --> 00:07:23,750
you learned about just now. Pause the video and complete the challenge.

110
00:07:25,400 --> 00:07:29,510
All right. So the first thing you notice is that the label is still at column

111
00:07:29,510 --> 00:07:33,590
zero row zero, button is still at row one column one,

112
00:07:33,980 --> 00:07:38,690
but this new button is now at row zero column two.

113
00:07:39,350 --> 00:07:41,060
So let's go ahead and create it.

114
00:07:41,960 --> 00:07:46,370
Now I'm just going to create a new button and I'm not going to worry about its

115
00:07:46,370 --> 00:07:47,720
command or any of that.

116
00:07:48,050 --> 00:07:51,830
I'll give it a piece of text just so that we can identify it and I'll call it

117
00:07:51,830 --> 00:07:52,700
new button.

118
00:07:53,240 --> 00:07:57,530
But then the most important thing is how we lay out this new button.

119
00:07:58,010 --> 00:08:02,990
So I'm going to use the grid system and I'm going to give it a column of two

120
00:08:03,260 --> 00:08:05,990
because it is zero, one, two,

121
00:08:06,170 --> 00:08:10,550
the third column from the left and then row is going to be zero.

122
00:08:13,580 --> 00:08:17,090
Now, when I run this code though, you'll notice something a little bit odd.

123
00:08:17,510 --> 00:08:21,980
Why is the entry below the button? Because in our example,

124
00:08:22,040 --> 00:08:26,750
the entry is actually over on the right of this new button in a new column.

125
00:08:27,500 --> 00:08:31,520
By putting this new button in between the old button and the entry, we've

126
00:08:31,520 --> 00:08:34,940
actually changed the positioning of that entry on the grid.

127
00:08:35,240 --> 00:08:39,350
So we've actually had to move it along into the next column.

128
00:08:39,950 --> 00:08:41,000
So to do that,

129
00:08:41,030 --> 00:08:46,030
we have to change the grid of our entry instead of having column two,

130
00:08:46,520 --> 00:08:51,380
to make it column three, just so that its on the right of this new button.

131
00:08:52,130 --> 00:08:55,890
And now when I run it, this has the exact layout that we wanted

132
00:08:56,280 --> 00:09:01,080
and we've now learned a little bit about how we can precisely position our

133
00:09:01,080 --> 00:09:06,080
widgets in our program using the pack, place, and grid layout managers.

134
00:09:08,610 --> 00:09:13,610
The very last thing I want to show you with relation to layout and design of our

135
00:09:14,730 --> 00:09:19,320
GUI programs is how to add a little bit of padding around components.

136
00:09:19,920 --> 00:09:24,920
The easiest way to add padding is actually to directly modify the widgets.

137
00:09:25,410 --> 00:09:26,310
So for example,

138
00:09:26,310 --> 00:09:30,450
if I wanted a bit of padding around all of the elements in my window,

139
00:09:30,450 --> 00:09:33,570
so basically added around the edge of the window,

140
00:09:33,960 --> 00:09:38,960
then I could simply say window.config and I can change the padding in the X

141
00:09:42,060 --> 00:09:45,900
axis and the padding in the Y axis,

142
00:09:45,930 --> 00:09:48,360
so padx and pady.

143
00:09:48,870 --> 00:09:51,990
So now if I run this program as it is,

144
00:09:52,290 --> 00:09:57,290
you can see that there's now more space being added around all four edges of our

145
00:09:58,320 --> 00:10:02,190
program. Now I can make this a lot more extreme.

146
00:10:02,190 --> 00:10:07,190
So let's say I add the padx to be 100 and the pady to be 200,

147
00:10:08,610 --> 00:10:11,340
you can see just how much padding we've now added.

148
00:10:12,450 --> 00:10:16,170
And this just means that you add more space around your program and it makes

149
00:10:16,170 --> 00:10:19,380
things easier to see and looks a little bit nicer.

150
00:10:20,670 --> 00:10:25,080
If you want to add padding around a specific widget not just the entire window,

151
00:10:25,350 --> 00:10:30,350
then you can do the same with that widget. So we could get hold of my label and

152
00:10:30,480 --> 00:10:30,750
again

153
00:10:30,750 --> 00:10:35,750
using config to change the padx and the pady. So let's add, maybe I dunno,

154
00:10:36,720 --> 00:10:41,310
50 pixels of padding in the X and in the Y.

155
00:10:43,320 --> 00:10:45,570
Now you can see that around that label

156
00:10:45,600 --> 00:10:50,490
there's a whole lot of space so that it pushes everything else away and actually

157
00:10:50,490 --> 00:10:53,010
makes the entire program window a lot bigger.

158
00:10:53,640 --> 00:10:58,640
So this is just a way for you to be able to add space around your widgets so

159
00:10:59,160 --> 00:11:00,840
that they're not all crushed together

160
00:11:01,080 --> 00:11:03,480
and it helps you with your layout and your design.

