Có một số tùy chọn để xây dựng các ứng dụng GUI với Python, bao gồm và . Tuy nhiên, hướng dẫn này sẽ giới thiệu cho bạn về .
Tkinter , viết tắt của "Tk interface", là tiêu chuẩn của Python để xây dựng GUI và được bao gồm trong . Nó là một ràng buộc với bộ công cụ Tk GUI , một thư viện mã nguồn mở miễn phí của các tiện ích GUI có thể được sử dụng để xây dựng giao diện đồ họa bằng nhiều ngôn ngữ lập trình.
Hướng dẫn này trình bày về thiết kế của một ứng dụng GUI cơ bản hiển thị giờ địa phương trong múi giờ do người dùng chọn. Các bước xây dựng ứng dụng dần dần và mô tả một số khái niệm chính khi làm việc với Tkinter , bao gồm cách bố trí các phần tử GUI, thu thập thông tin đầu vào của người dùng và liên kết các phần tử GUI với các phương thức gọi lại.
pip
cài đặt.pytz
. Thư viện có thể được cài đặt bằng pip
.
pip install pytz
Hướng dẫn này sẽ sử dụng thuật ngữ cửa sổ gốc và cửa sổ chính thay thế cho nhau.
Tạo một ứng dụng Python mới có tên timezone.py
và thêm các câu lệnh import
sau để nhập các mô-đun Tkinter
, datetime
và pytz
.
import tkinter as tk import datetime import pytz
Hướng dẫn này kết hợp bộ múi giờ của Hoa Kỳ là một phần nhỏ của múi giờ được pytz
hỗ trợ. Chức năng của ứng dụng có thể được mở rộng bằng cách thêm các tên múi giờ pytz
bổ sung. Có thể xuất danh sách đầy đủ các múi giờ có sẵn với pytz
bằng cách chạy lệnh sau:
print(pytz.all_timezones)
Bộ múi giờ của Hoa Kỳ có sẵn qua pytz
được chỉ định dưới dạng danh sách.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"]
Khởi tạo lớp Tk
tạo ra một cửa sổ gốc sẽ đóng vai trò là cửa sổ chính của GUI của ứng dụng múi giờ.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk()
Tiêu đề cửa sổ được đặt bằng phương pháp title
.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application")
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175
Cửa sổ chính có thể được đặt ở bất kỳ vị trí nào trên màn hình, ví dụ như ở giữa, ở góc trên bên trái, v.v. Cửa sổ căn giữa cung cấp "giao diện" đẹp mắt và vị trí trung tâm của cửa sổ chính có thể được xác định bằng cách sử dụng winfo_screenwidth()
của cửa sổ gốc. winfo_screenwidth()
và các phương thức winfo_screenheight()
cùng với một số phép toán đơn giản. Hai phương thức này trả về chiều rộng màn hình và chiều cao màn hình được sử dụng để tính toán tọa độ (x, y) thích hợp để căn giữa cửa sổ chính. Như với chiều rộng và chiều cao của cửa sổ, các giá trị vị trí trung tâm cũng có thể được gán cho các biến để làm cho mã dễ đọc hơn.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2)
Lưu ý rằng giá trị center_x
và center_y
cũng được biểu thị bằng pixel và int
được sử dụng để đảm bảo cả hai giá trị được tính toán đều là số nguyên.
Hình học cửa sổ root
, chỉ định kích thước và vị trí của cửa sổ chính, được thiết lập bằng phương pháp geometry
của cửa sổ gốc. Để làm cho mọi thứ trở nên đơn giản, bạn có thể sử dụng một chuỗi ký tự sting được định dạng, hoặc chuỗi f , sẽ nội suy các biểu thức biến hình học trong thời gian chạy. Theo khối mã sau, chuỗi ký tự f được chuyển đến phương thức geometry
dưới dạng tham số.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
Khả năng thay đổi kích thước của cửa sổ gốc dọc theo trục x và y của nó có thể được đặt thông qua phương pháp resizable
của cửa sổ gốc. Phương thức resizable
chấp nhận các tham số height
và width
, theo thứ tự đó. Giá trị True
hoặc khác 0 cho một trong hai tham số chỉ định rằng cửa sổ chính có thể thay đổi kích thước dọc theo trục được liên kết. Giá trị False
hoặc 0
cho một trong hai tham số chỉ định rằng cửa sổ chính không thể thay đổi kích thước dọc theo trục đã cho. Ứng dụng hẹn giờ sẽ sử dụng giá trị False
cho cả chiều cao và chiều rộng để ngăn cửa sổ chính bị thay đổi kích thước.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False)
Các widget có thể được sắp xếp trên đầu cửa sổ chính theo nhiều cách khác nhau bằng cách sử dụng trình quản lý hình học . Nói chung, các widget có thể được sắp xếp theo 3 cách:
Được đóng gói bằng phương thức pack()
. Trình quản lý hình học pack()
sắp xếp các widget thành các khối trước khi chúng được thêm vào cửa sổ gốc hoặc widget cha. Một cách không hoàn hảo nhưng có lẽ hữu ích để nghĩ về việc đóng gói là nghĩ về việc thêm các mặt hàng tạp hóa vào một túi hàng tạp hóa. Các mục không nhất thiết phải được thêm vào các vị trí được xác định trước trong túi. Thay vào đó, chúng được đóng gói lần lượt, sử dụng hết không gian có sẵn cho đến khi tất cả các mặt hàng đã được cho vào túi. Trình quản lý hình học pack()
hoạt động theo cách tương tự.
Được đặt bằng phương thức place()
. Trình quản lý hình học place()
đặt các tiện ích con vào các vị trí cụ thể, được xác định trước trong cửa sổ gốc hoặc tiện ích con. Trình quản lý hình học này rõ ràng là hữu ích khi xây dựng bố cục GUI chính xác.
Được sắp xếp dưới dạng lưới bằng cách sử dụng phương thức grid()
. Lưới là bảng hàng / cột 2 chiều. Tiện ích con được thêm vào lưới bằng cách chỉ định hàng và cột cụ thể nơi tiện ích con sẽ được đặt. Lưới được thiết lập bằng phương pháp columnconfigure
và rowconfigure
của cửa sổ gốc. Mỗi phương pháp này có một index
và một thuộc tính weight
. Thuộc tính index
định vị trí của cột hoặc hàng bằng cách sử dụng cơ sở bắt đầu là 0
. Thuộc tính weight
chỉ định kích thước của một cột hoặc hàng cụ thể so với các cột khác. Ví dụ, nếu cột 0 có trọng số 1
và cột 1 có trọng số 3
, thì cột 1 sẽ lớn gấp 3 lần cột 0 .
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1)
Trong bước này, các widget được thêm vào lưới cửa sổ chính được xác định trong Bước 4. Ứng dụng múi giờ sẽ sử dụng 3 widget TKinter :
Label
Listbox
Button
Các widget Label
và Button
của Tkinter đúng như tên gọi của chúng. Tiện ích Label
cho phép người lập trình hiển thị văn bản (tức là nhãn), và tiện ích Button
được sử dụng để hiển thị các nút. Listbox
ích Hộp danh sách được sử dụng để chọn một giá trị (hoặc các giá trị) từ danh sách các tùy chọn.
Tất nhiên, có những widget khác ngoài 3 widget được liệt kê ở trên, chẳng hạn như các SpinBox
, Entry
và Message
. chính thức là một tài nguyên hữu ích để tìm hiểu thêm về các tiện ích con có sẵn thông qua bộ công cụ Tk.
Một phiên bản của mỗi lớp widget được tạo cho một widget nhất định được sử dụng với thiết kế GUI. Ứng dụng múi giờ sử dụng 4 phiên bản tiện ích con: 2 tiện ích Label
, 1 Listbox
ích Hộp danh sách và 1 tiện ích Button
.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="")
Như đã thấy trong khối mã ở trên, mỗi cá thể widget được "đính kèm" vào cửa sổ root
. Tiện ích Listbox
cũng yêu cầu khởi tạo lớp Tkinter Variable()
đặc biệt được sử dụng để cung cấp cho widget danh sách các tùy chọn múi giờ mà người dùng có thể chọn thông qua thuộc tính listvariable
Listbox
. Văn bản được hiển thị bởi mỗi tiện ích Label
có thể được định cấu hình bằng cách sử dụng thuộc tính text
. Giá trị văn bản cho time_label
được để trống vì nó sẽ được đặt động mỗi khi người dùng "lấy" thời gian cho một múi giờ đã chọn.
Các cá thể widget được tạo ở Bước 5a có thể được đặt trên lưới được xác định trong Bước 4 bằng cách sử dụng phương thức grid()
. Ứng dụng múi giờ sẽ sử dụng các thuộc tính phương thức grid()
sau để xác định bố cục:
column
: Chỉ định cột cụ thể nơi tiện ích con sẽ được đặt bằng cách sử dụng cơ sở 0
.
row
: Chỉ định hàng cụ thể nơi tiện ích con sẽ được đặt bằng cách sử dụng cơ sở 0
.
columnspan
: Chỉ định rằng widget sẽ kéo dài số cột được chỉ định. Ví dụ: một tiện ích con có giá trị cột columnspan=3
sẽ kéo dài 3 cột ngay cả khi chính tiện ích con đó nhỏ hơn 3 cột.
sticky
: Hành vi mặc định của Tkinter là đặt tiện ích con ở tâm ngang và dọc của ô (tức là vị trí hàng / cột cụ thể) nơi nó được đặt. Hành vi mặc định này có thể được ghi đè bằng cách sử dụng sticky
tính cố định sử dụng các giá trị giống như la bàn, bao gồm NW
, N
, NE
, W
, E
, SW
, S
và SE
, để căn chỉnh tiện ích tại một vị trí cụ thể trong ô của tiện ích. Ví dụ: sticky=tK.W
chỉ định rằng tiện ích con phải được căn chỉnh về góc phía tây của ô lưới của nó. Tương tự, sticky=tK.E
chỉ định rằng tiện ích con phải được căn chỉnh theo góc phía đông của ô lưới của nó.
padx
, pady
: Thuộc tính padx
và pady
được sử dụng để thêm đệm trục x và trục y tương ứng với các giá trị được chỉ định bằng pixel. Đương nhiên, padding có thể cung cấp một GUI trông chuyên nghiệp hơn, đảm bảo rằng các widget không "va chạm" trực tiếp vào các cạnh của cửa sổ gốc hoặc các widget khác.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10)
Phương thức gọi lại cần được xác định để xử lý các sự kiện khi người dùng nhấp vào nút select_timezone_button
được tạo ở Bước 5.
Trước khi xác định logic gọi lại, điều hữu ích là đầu tiên liên kết nút với tên phương thức mà cuối cùng sẽ bao gồm mã gọi lại. Phương thức bind()
có thể được sử dụng cùng với một hàm lambda
để liên kết select_timezone_button
với phương thức gọi lại được chỉ định. Ngoài ra, hãy lưu ý rằng hàm lambda
được sử dụng để chuyển các tham chiếu đến các widget select_timezone_listbox
và time_label
dưới dạng các tham số gọi lại. Các thông số gọi lại này thực sự không cần thiết vì select_timezone_listbox
và time_label
đều nằm trong phạm vi chung. Tuy nhiên, nó được cho là hữu ích để chứng minh cách các đối số có thể được truyền cho hàm gọi lại.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_button.bind("<Button>", lambda e, args=[select_timezone_listbox, time_label]: get_timezone_time(e, args))
def get_timezone_time(e, args): select_timezone_listbox = args[0] time_label = args[1] selection_index = select_timezone_listbox.curselection() selected_timezone = select_timezone_listbox.get(selection_index) now_time = datetime.datetime.now() tz_time = now_time.astimezone(pytz.timezone(selected_timezone)) tz_formatted = tz_time.strftime("%H:%M:%S") time_label.configure({"text": f"The time in {selected_timezone} is {tz_formatted}."}) time_label.update()
Các curselection()
và get()
được sử dụng để truy xuất múi giờ đã chọn của người dùng từ tham chiếu đến tiện ích con select_timezone_listbox
. Thời gian hiện tại của người dùng sau đó được chuyển đổi thành múi giờ đã chọn. Cuối cùng, phương thức configure
được sử dụng để thay đổi thuộc tính text
của tham chiếu đến nhãn thời time_label
với giờ địa phương trong múi giờ đã chọn. Lưu ý rằng phương thức update()
được sử dụng để "buộc" tiện ích time_label
tự cập nhật giá trị văn bản mới.
Phương thức mainloop()
của cửa sổ gốc được áp dụng làm dòng mã cuối cùng. Phương thức mainloop()
sẽ chạy GUI trong một vòng lặp vô hạn cho đến khi người dùng thoát.
import tkinter as tk import datetime import pytz timezones = ["US/Alaska", "US/Aleutian", "US/Arizona", "US/Central", "US/East-Indiana", "US/Eastern", "US/Hawaii", "US/Indiana-Starke", "US/Michigan", "US/Mountain", "US/Pacific", "US/Samoa"] def get_timezone_time(e, args): select_timezone_listbox = args[0] time_label = args[1] selection_index = select_timezone_listbox.curselection() selected_timezone = select_timezone_listbox.get(selection_index) now_time = datetime.datetime.now() tz_time = now_time.astimezone(pytz.timezone(selected_timezone)) tz_formatted = tz_time.strftime("%H:%M:%S") time_label.configure({"text": f"The time in {selected_timezone} is {tz_formatted}."}) time_label.update() root = tk.Tk() root.title("Simple Timezone Application") window_width = 450 window_height = 175 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() center_x = int((screen_width - window_width)/2) center_y = int((screen_height - window_height)/2) root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}") root.resizable(False, False) root.columnconfigure(0, weight=1) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=1) root.columnconfigure(3, weight=1) # Instance of Label widget class for selection prompt. select_timezone_label = tk.Label(root, text="Please select a timezone.") # Instance of Listbox class for selection of timezone from list. list_var = tk.Variable(value=timezones) select_timezone_listbox = tk.Listbox(root, listvariable=list_var, height=1) # Instance of Button class to get the local time in the selected timezone. select_timezone_button = tk.Button(root, text="Get Time") # Second instance of the Label class to display the local time in the selected timezone. time_label = tk.Label(root, text="") # Place widgets on grid. select_timezone_label.grid(column=0, row=0, columnspan=4, sticky=tk.W, padx=10, pady=10) select_timezone_listbox.grid(column=0, row=1, columnspan=3, sticky=tk.EW, padx=10, pady=10) select_timezone_button.grid(column=4, row=1, sticky=tk.E, padx=10, pady=10) time_label.grid(column=0, row=4, columnspan=4, sticky=tk.W, padx=10, pady=10) # Bind button to callback. select_timezone_button.bind("<Button>", lambda e, args=[select_timezone_listbox, time_label]: get_timezone_time(e, args)) root.mainloop()
Để sử dụng ứng dụng, hãy nhấp vào hộp danh sách và sử dụng các phím con trỏ lên / xuống của bàn phím để cuộn qua các tùy chọn múi giờ. Nhấp vào nút Lấy thời gian để hiển thị thời gian hiện tại trong múi giờ đã chọn của bạn.
Chúc mừng bạn đã xây dựng ứng dụng GUI Python đầu tiên của mình với Tkinter ! Như đã đề cập trong phần Giới thiệu, hướng dẫn này được thiết kế để giới thiệu cho bạn một vài khái niệm cơ bản. và tài liệu tham khảo được đề cập trước đó là hai tài nguyên tuyệt vời để giúp bạn tìm hiểu về các tính năng và chức năng Tkinter nâng cao hơn.