Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Trình quản lý hình học Pack trong Tkinter
Trong việc phát triển ứng dụng giao diện người dùng (GUI) bằng Python, Tkinter là một trong những thư viện phổ biến nhất. Để tổ chức và sắp xếp các thành phần giao diện (widget) trên màn hình, Tkinter cung cấp nhiều trình quản lý hình học, trong đó Pack là một công cụ quan trọng và dễ sử dụng. Trong bài viết này, mình sẽ tìm hiểu cách sử dụng trình quản lý hình học Pack, tìm hiểu các tùy chọn của nó và cách áp dụng chúng để tạo ra các bố cục giao diện trực quan và hiệu quả. Bằng cách hiểu rõ về Pack, bạn sẽ có thể sắp xếp các widget một cách logic và tối ưu hóa trải nghiệm người dùng cho ứng dụng của mình.
Giới thiệu về trình quản lý hình học pack của Tkinter
Tkinter sử dụng các trình quản lý hình học để tổ chức các widget trên cửa sổ. Tkinter hỗ trợ ba trình quản lý hình học:
- pack
- grid
- place
Trình quản lý hình học pack tổ chức các widget thành các khối trước khi đặt chúng lên container widget, có thể là cửa sổ chính hoặc một khung (frame).
Các tùy chọn của trình quản lý hình học pack
Trình quản lý hình học pack có nhiều tùy chọn để sắp xếp các widget, bao gồm:
Bài viết này được đăng tại [free tuts .net]
- Side (Hướng)
- Expand (Mở rộng)
- Fill (Lấp đầy)
- ipadx, ipady (Đệm bên trong)
- padx, pady (Đệm bên ngoài)
- Anchor (Điểm neo)
Trước khi đi sâu vào từng tùy chọn, bạn cần hiểu về tọa độ x và y của cửa sổ:
Góc trên bên trái của cửa sổ là gốc với tọa độ (0,0). Tọa độ x tăng từ trái sang phải và tọa độ y tăng từ trên xuống dưới.
Các tham số của pack trong Tkinter
Chúng ta sẽ tạo một chương trình đơn giản để minh họa cách hoạt động của trình quản lý hình học pack:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack() label2.pack() label3.pack() root.mainloop()
Chương trình trên tạo ra một cửa sổ chính với ba nhãn có màu nền lần lượt là đỏ, xanh lá cây và xanh dương.
Để sử dụng trình quản lý hình học pack, bạn gọi phương thức pack()
của widget. Mặc định, trình quản lý pack sắp xếp các widget theo chiều dọc từ trên xuống dưới.
Tùy chọn Side (Hướng)
Tham số side
xác định hướng sắp xếp của các widget trong bố cục pack.
Tham số side
có bốn tùy chọn:
'top'
: sắp xếp các widget từ trên xuống dưới theo chiều dọc.'bottom'
: sắp xếp các widget từ dưới lên trên theo chiều dọc.'left'
: sắp xếp các widget từ trái sang phải theo chiều ngang.'right'
: sắp xếp các widget từ phải sang trái theo chiều ngang.
Mặc định, side
là 'top'
, sắp xếp các widget theo chiều dọc từ trên xuống dưới.
Ngoài các hằng chuỗi, bạn có thể sử dụng các hằng số định sẵn được cung cấp bởi module Tkinter:
tk.TOP
tk.BOTTOM
tk.LEFT
tk.RIGHT
Ví dụ, chương trình sau đây đặt side
là 'top'
, sắp xếp các nhãn theo chiều dọc từ trên xuống dưới:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.TOP) label2.pack(side=tk.TOP) label3.pack(side=tk.TOP) root.mainloop()
Khi thay đổi side
thành tk.BOTTOM
, các nhãn sẽ được sắp xếp từ dưới lên trên theo chiều dọc:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.BOTTOM) label2.pack(side=tk.BOTTOM) label3.pack(side=tk.BOTTOM) root.mainloop()
Kết quả:
Không gian của widget
Trong Tkinter, có hai loại không gian:
- Không gian mà một widget có thể chiếm: Là không gian mà container widget cung cấp cho widget.
- Không gian mà widget sẽ chiếm: Là không gian thực tế mà widget chiếm trong container.
Mặc định, một widget chỉ chiếm không gian cần thiết để hiển thị nội dung của nó. Tuy nhiên, một widget có thể chiếm nhiều không gian hơn nếu được chỉ định.
Ví dụ, một widget Label sẽ có kích thước tương ứng với văn bản. Màu nền cho thấy mỗi nhãn có chiều rộng khác nhau vì độ dài của văn bản khác nhau.
Tùy chọn Expand (Mở rộng)
Tham số expand
xác định liệu widget có nên mở rộng để chiếm không gian trống được phân bổ cho container hay không.
Nếu expand
được đặt là True
, widget sẽ mở rộng, và nếu được đặt là False
, nó sẽ không mở rộng. Mặc định, expand
là False
.
Tham số expand
phụ thuộc rất nhiều vào tham số side
.
Bảng sau minh họa sự phụ thuộc giữa tham số side
và expand
khi xét đến không gian của widget:
Side (Hướng) | Expand (Mở rộng) |
---|---|
Top (hoặc Bottom) | Widget có thể rộng bằng container, expand sẽ xác định chiều cao của widget. |
Left (hoặc Right) | Widget có thể cao bằng container, expand sẽ xác định chiều rộng của widget. |
Chương trình sau đây sắp xếp các widget Label theo chiều dọc từ trên xuống dưới và đặt tham số expand
của widget Label đầu tiên là True
và của hai widget Label còn lại là False
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.TOP, expand=True) label2.pack(side=tk.TOP, expand=False) label3.pack(side=tk.TOP, expand=False) root.mainloop()
Vì tham số expand
của Label đầu tiên được đặt là True
, nó chiếm toàn bộ không gian dọc và đẩy hai widget Label còn lại xuống dưới.
Chương trình sau đây sắp xếp các widget Label theo chiều ngang từ trái sang phải và đặt tham số expand
của widget Label đầu tiên là True
và của hai widget Label còn lại là False
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.LEFT, expand=True) label2.pack(side=tk.LEFT, expand=False) label3.pack(side=tk.LEFT, expand=False) root.mainloop()
Vì tham số expand
của Label đầu tiên được đặt là True
, nó chiếm toàn bộ không gian ngang và đẩy hai widget Label còn lại về bên phải.
Nếu bạn đặt tham số expand
của cả ba widget Label là True
, chúng sẽ chiếm đều không gian ngang:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.LEFT, expand=True) label2.pack(side=tk.LEFT, expand=True) label3.pack(side=tk.LEFT, expand=True) root.mainloop()
Tùy chọn Fill (Lấp đầy)
Tham số fill
xác định liệu một widget có chiếm hết không gian sẵn có hay không. Nó chấp nhận các giá trị sau: 'x'
, 'y'
, 'both'
, và 'none'
. Mặc định, fill
là 'none'
.
fill | Tác dụng |
---|---|
x | Mở rộng widget theo chiều ngang của container. |
y | Mở rộng widget theo chiều dọc của container. |
both | Mở rộng widget theo cả chiều ngang và chiều dọc của container. |
none | Không mở rộng widget. Đây là giá trị mặc định nếu fill không được chỉ định. |
Bảng sau đây minh họa sự phụ thuộc giữa tham số side
và fill
khi xét đến không gian của widget:
Side (Hướng) | Fill (Lấp đầy) |
---|---|
Top (hoặc Bottom) | Widget có thể rộng bằng container, fill sẽ xác định chiều rộng của widget. |
Left (hoặc Right) | Widget có thể cao bằng container, fill sẽ xác định chiều cao của widget. |
Chương trình sau đây sắp xếp các widget Label theo chiều dọc từ trên xuống dưới và đặt tham số fill
của tất cả các widget Label là 'x'
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.TOP, fill=tk.X) label2.pack(side=tk.TOP, fill=tk.X) label3.pack(side=tk.TOP, fill=tk.X) root.mainloop()
Các widget Label chiếm toàn bộ chiều ngang của container, nhưng không chiếm chiều dọc.
Chương trình sau đây sắp xếp các widget Label theo chiều ngang từ trái sang phải và đặt tham số fill
của tất cả các widget Label là 'y'
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.LEFT, fill=tk.Y) label2.pack(side=tk.LEFT, fill=tk.Y) label3.pack(side=tk.LEFT, fill=tk.Y) root.mainloop()
Các widget Label chiếm toàn bộ chiều dọc của container, nhưng không chiếm chiều ngang.
Chương trình sau đây sắp xếp các widget Label theo chiều dọc từ trên xuống dưới và đặt tham số fill
của tất cả các widget Label là 'both'
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(side=tk.TOP, fill=tk.BOTH) label2.pack(side=tk.TOP, fill=tk.BOTH) label3.pack(side=tk.TOP, fill=tk.BOTH) root.mainloop()
Các widget Label chiếm toàn bộ không gian của container.
Đệm bên trong (ipadx, ipady)
Tham số ipadx
xác định khoảng cách theo chiều ngang giữa nội dung và biên của widget. Tương tự, ipady
xác định khoảng cách theo chiều dọc giữa nội dung và biên của widget.
Nếu bạn không chỉ định các tham số ipadx
và ipady
, các widget sẽ không có đệm bên trong.
Chương trình sau đây đặt ipadx
là 10 và ipady
là 5 cho tất cả các widget Label:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(ipadx=10, ipady=5) label2.pack(ipadx=10, ipady=5) label3.pack(ipadx=10, ipady=5) root.mainloop()
Kết quả:
Tùy chọn Anchor (Điểm neo)
Tham số anchor
xác định vị trí của widget trên container widget. Nó chấp nhận các giá trị sau:
'n'
: trên cùng'e'
: bên phải's'
: dưới cùng'w'
: bên trái'center'
: trung tâm'ne'
: góc trên bên phải'nw'
: góc trên bên trái'se'
: góc dưới bên phải'sw'
: góc dưới bên trái
Chương trình sau đây đặt anchor
của các widget Label đầu tiên và thứ hai lần lượt là 'n'
và 'se'
:
import tkinter as tk root = tk.Tk() root.title('Tkinter Pack Layout') root.geometry('600x400') label1 = tk.Label(master=root, text='Tkinter', bg='red', fg='white') label2 = tk.Label(master=root, text='Pack Layout', bg='green', fg='white') label3 = tk.Label(master=root, text='Demo', bg='blue', fg='white') label1.pack(anchor='n') label2.pack(anchor='se') label3.pack(anchor='center') root.mainloop()
Kết quả:
Kết bài
Mình đã cùng tìm các tính năng và tùy chọn của trình quản lý hình học Pack trong Tkinter. Từ việc sắp xếp các widget theo hướng dọc hoặc ngang, đến việc điều chỉnh kích thước và khoảng cách của chúng bằng các tham số như expand
, fill
, padx
, pady
, ipadx
, và ipady
, Pack cung cấp một cách tiếp cận linh hoạt và hiệu quả để thiết kế giao diện người dùng. Hiểu và áp dụng đúng các tùy chọn của Pack sẽ giúp bạn tạo ra các giao diện đẹp mắt và dễ sử dụng cho ứng dụng của mình. Hãy thử nghiệm và điều chỉnh các tham số này để tìm ra giải pháp tốt nhất cho nhu cầu thiết kế của bạn, và nhớ rằng việc làm quen với các trình quản lý hình học khác như Grid và Place cũng sẽ mở rộng khả năng của bạn trong việc xây dựng giao diện Tkinter. Chúc bạn thành công trong việc phát triển các ứng dụng Tkinter của mình!