Tại sao sử dụng các lớp khi lập trình một gui tkinter trong python


19

Tôi lập trình chủ yếu bằng python và đã lập trình một vài GUI với Tkinter, mọi hướng dẫn tôi từng thấy đều khuyên bạn nên xác định và sử dụng một lớp cho GUI, nhưng GUI của tôi chạy hoàn hảo chỉ bằng các thủ tục, không có lớp.

Tại sao nên sử dụng một lớp học? Dường như từ quan điểm của tôi chỉ đơn giản là một lớp phức tạp thêm và mã không cần thiết.

Câu trả lời:


19

Tại sao nên sử dụng một lớp học? Bởi vì nó làm cho công việc dễ dàng hơn, giả sử bạn biết cách thực hiện lập trình hướng đối tượng và giả sử bạn đang viết một GUI không tầm thường. Sử dụng các đối tượng cho phép bạn dễ dàng phân chia mã của mình thành các đơn vị mô-đun khép kín và mô đun hóa mã của bạn thường được coi là một cách thực hành tốt nhất.

Lập trình GUI dễ dàng cho vay theo kiểu hướng đối tượng, vì GUI được tạo thành hoàn toàn từ các đối tượng - nhãn, nút, thanh cuộn, vùng văn bản, v.v. Vì bạn đã sử dụng các đối tượng, nên tổ chức mã của bạn thành các đối tượng lớn hơn . Thanh công cụ là một đối tượng, thanh trạng thái là một đối tượng, khung điều hướng là một đối tượng, khu vực chính là một đối tượng, mỗi tab sổ ghi chép là một đối tượng, v.v.

Ngay cả khi mã của bạn không quá phức tạp, từ quan điểm thực tế hơn, nó cho phép bạn xác định các ràng buộc và gọi lại sớm hơn trong tệp so với định nghĩa của hàm bạn đang gọi, điều mà tôi nghĩ rất có ý nghĩa.

Ví dụ, hãy xem xét một ví dụ đơn giản (giả sử rằng tkinter đã được nhập như import tkinter as tk(python3) hoặc import Tkinter as tk(python2):

def quit(event=None):
    sys.exit()
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack()
label.bind("<1>", quit)
root.mainloop()

Đối với tôi, dòng mã đó là tất cả sai. Tôi phải xác định phương thức thoát trước khi tôi tham chiếu nó, và việc tạo cửa sổ gốc và lệnh gọi tới mainloop được phân tách bằng tất cả các mã khác.

Tuy nhiên, bằng cách sử dụng các lớp, tôi có thể viết mã theo thứ tự tự nhiên hơn:

class MyWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Hello, world")
        label.pack()
        label.bind("<1>", self.quit)
    def quit(self, event=None):
        sys.exit()

root = tk.Tk()
MyWindow(root).pack()
root.mainloop()

Phần chính của GUI nằm ngay trên cùng của tệp và mã hỗ trợ nằm bên dưới nó. Bây giờ, tất nhiên, bạn có thể sử dụng các chức năng để đạt được nhiều điều tương tự. Tuy nhiên, theo tôi, các lớp học làm cho tất cả chỉ dễ dàng hơn một chút.

Một lợi thế khác là bây giờ tôi có thể dễ dàng thay đổi cửa sổ chứa mà không phải thay đổi bất cứ điều gì về cửa sổ "chính" (và ngược lại là visa). Đó là, tôi có thể thêm các đường viền hoặc một phần hoàn toàn mới vào GUI chính, nhưng tôi không phải chạm vào một dòng mã nào bên trong MyWindow. Ngược lại với mã thủ tục nơi bạn có thể phải thay đổi label.pack()câu lệnh và các câu lệnh gói (hoặc lưới) của tất cả các widget khác trong UI.

Tuy nhiên, tất cả những gì đang được nói, sử dụng một cách tiếp cận hướng đối tượng là không cần thiết để viết mã tốt, sạch, có thể bảo trì. Nó thể, nhưng nó cũng có thể dẫn đến mã kém. Vào cuối ngày, một cách tiếp cận hướng đối tượng chỉ là một công cụ. Việc bạn có sử dụng hay không, và bạn có sử dụng đúng hay không phụ thuộc vào rất nhiều yếu tố. Vì vậy, nó rất có thể là đối với bạn, và đối với mã bạn viết, một phong cách chức năng là hoàn toàn chấp nhận được. Tôi nghĩ bạn sẽ thấy rằng khi các chương trình của bạn trở nên phức tạp hơn, một cách tiếp cận hướng đối tượng sẽ giúp việc tổ chức và duy trì mã của bạn dễ dàng hơn.


Tại sao bạn sử dụng Frame trong ví dụ thứ hai? Bạn không thể tránh nó như bạn đã làm trong ví dụ đầu tiên? Có bí mật nào đằng sau việc sử dụng Frame với các lớp không?
đa cấp

2
Khung đơn giản là để thuận tiện. Không có bí mật để kế thừa từ Frame. Tôi có thể đã được thừa hưởng từ objecthoặc bất kỳ lớp nào khác, nhưng cuối cùng tôi thường tạo ra một khung. Nếu tôi đặt mọi thứ vào một khung, sẽ rất hợp lý khi biến lớp thành khung. .
Bryan Oakley

1
Làm cho ý nghĩa, cảm ơn! Ngoài ra, tôi đã thấy những người khác sử dụng bản thân trước các biến, nhưng tôi thấy bạn đang sử dụng một cái gì đó giống như label=tk.Label()thay vì self.tk.Label(). Đó có phải là một sự lựa chọn phong cách? Dưới đây là một ví dụ sử dụng self: python-textbok.readthedocs.org/en/1.0/ mẹo
multigoodverse

1
@BryanOakley, tôi đoán bạn có nghĩa là sử dụng cha mẹ thay vì root trong dòng sau của MyWindow .__ init__: "nhãn = tk.Label (root, text =" Hello, world ")"
user3885927

1
@ user3885927: có! Wow, phải mất gần ba năm để ai đó nhận ra điều đó. Mặc dù, không phải, parentnhưng đúng hơn self, vì bản thân lớp là Khung. Cảm ơn!
Bryan Oakley
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.