Python 为什么要将框架和小部件放在类中?

Python 为什么要将框架和小部件放在类中?,python,class,optimization,tkinter,code-organization,Python,Class,Optimization,Tkinter,Code Organization,正如问题所述,我似乎不能完全理解将类与tkinter一起使用的意义 我已经浏览了很多不同的网站,但我一直在获得关于如何创建和使用类的搜索结果,但到目前为止,没有一个网站能够让我理解。我甚至在问这个问题的时候仔细检查了建议的问题。我最能理解的是布莱恩对这个问题的解释 但是,我还是觉得我快到了,只是还没有完全超越理解的边缘 在链接中的例子中,他创建了一个非传统的程序,然后创建了一个更好、更传统的程序来做同样的事情。我知道它所代表的规模比千行程序小得多,而千行程序可以真正受益于面向对象的方法 是否每个

正如问题所述,我似乎不能完全理解将类与tkinter一起使用的意义

我已经浏览了很多不同的网站,但我一直在获得关于如何创建和使用类的搜索结果,但到目前为止,没有一个网站能够让我理解。我甚至在问这个问题的时候仔细检查了建议的问题。我最能理解的是布莱恩对这个问题的解释

但是,我还是觉得我快到了,只是还没有完全超越理解的边缘

在链接中的例子中,他创建了一个非传统的程序,然后创建了一个更好、更传统的程序来做同样的事情。我知道它所代表的规模比千行程序小得多,而千行程序可以真正受益于面向对象的方法

是否每个小部件都需要在自己的单独框架中,而这可能是更大框架的一部分

类可以有创建和放置框架的方法吗?此外,这些类是否可以有方法来创建、修改和放置之前创建的框架中的小部件

我还有一些代码,允许我创建、修改和放置小部件。虽然我知道这不是传统的,所以我也非常感谢您在这方面的一些意见。关于如何使用此代码使其更好,您有什么建议吗

import tkinter as tk

def layout(self, row=0, column=0, columnspan=None, row_weight=None, column_weight=None, color=None, sticky=None, ipadx=None, padx=None, ipady=None, pady=None):
    self.grid(row=row, column=column, columnspan=columnspan, sticky=sticky, ipadx=ipadx, padx=padx, ipady=ipady, pady=pady)
    self.grid_rowconfigure(row, weight=row_weight)
    self.grid_columnconfigure(column, weight=column_weight)
    self.config(bg=color)

class MyLabels(tk.Label):
    def __init__(self, parent, text, **kwargs):
        tk.Label.__init__(self, parent, text=text)
        layout(self, **kwargs)

class MyButtons(tk.Button):
    def __init__(self, parent, text, command, **kwargs):
        tk.Button.__init__(self, parent, text=text, command=command)
        layout(self, **kwargs)


window = tk.Tk()
test_button = MyButtons(window, "hi", None, color="pink")
window.mainloop()

评论后编辑: 所以,从昨天开始,我已经工作了好几个小时,试图把你给我的想法结合起来。这就是我想到的:

import tkinter as tk

window = tk.Tk()

class MyWidgets(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.layout()

    def layout(self):
        self.grid(row=0, column=0)
        self.config(bg="blue")

class MyButtons(MyWidgets):
    def __init__(self, parent, text):
        MyWidgets.__init__(self, parent)
        tk.Button(parent, text=text)
        self.layout()

frme = MyWidgets(window)
btn = MyButtons(frme, text="Test")
window.mainloop()
我尝试过在这个小程序上移动东西并重写很多区域,尽管我能够证明
btn
实际上是在访问
self.config(bg=“blue”)
属性,但按钮似乎没有改变。事实上,在创建按钮之后,我无法找到一种不需要将
self.grid()
放入子类的方法来显示按钮

尽管如此,即使我添加了
self.grid()
,按钮仍然不会变成蓝色。它是不是与自我有关

为什么当子类创建按钮,而父类放置按钮时,按钮不出现

注意:我故意省略了整个
布局函数
,并将其替换为一个简单的
配置方法
。我想如果我能理解这一点,我就能找到一种方法将整个函数合并回代码中

是否每个小部件都需要在自己的单独框架中,而这可能是更大框架的一部分

这有点像问数学表达式的每一部分是否都需要括号。严格地说,答案是“不”。然而,使用框架来组织小部件组是一种旨在使编写和理解代码更容易的工具,就像复杂数学公式中的括号使编写和理解公式更容易一样

类可以有创建和放置框架的方法吗?此外,这些类是否可以有方法来创建、修改和放置之前创建的框架中的小部件

对,对。类中的方法对它们能做什么和不能做什么没有任何限制。类的方法可以做普通函数可以做的任何事情

我还有一些代码,允许我创建、修改和放置小部件。虽然我知道这不是传统的,所以我也非常感谢您在这方面的一些意见。关于如何使用此代码使其更好,您有什么建议吗

import tkinter as tk

def layout(self, row=0, column=0, columnspan=None, row_weight=None, column_weight=None, color=None, sticky=None, ipadx=None, padx=None, ipady=None, pady=None):
    self.grid(row=row, column=column, columnspan=columnspan, sticky=sticky, ipadx=ipadx, padx=padx, ipady=ipady, pady=pady)
    self.grid_rowconfigure(row, weight=row_weight)
    self.grid_columnconfigure(column, weight=column_weight)
    self.config(bg=color)

class MyLabels(tk.Label):
    def __init__(self, parent, text, **kwargs):
        tk.Label.__init__(self, parent, text=text)
        layout(self, **kwargs)

class MyButtons(tk.Button):
    def __init__(self, parent, text, command, **kwargs):
        tk.Button.__init__(self, parent, text=text, command=command)
        layout(self, **kwargs)


window = tk.Tk()
test_button = MyButtons(window, "hi", None, color="pink")
window.mainloop()
“更好”是非常主观的。对于20行代码来说更好的可能并不适合200、2000或20000行代码。对于一个只使用了两次的函数来说,更好的方法可能并不适用于一个使用了数百次或数千次的函数(反之亦然)

这就是说,您正在做一件非常非常规的事情,这会使代码更难理解:您正在使用
self
作为函数的参数,而函数不是类的方法
self
对python程序员来说意味着非常特殊的东西;在方法的上下文之外使用它是非常令人困惑的

对于方法
布局
,您应该执行以下两项操作之一:

  • self
    重命名为
    widget
    或除
    self
  • 创建一个定义
    布局的基类
    ,然后让您的类从基类继承。在这种情况下,
    self
    是正确的第一个参数

答案的这一部分是指在我写下原始答案后添加的代码

我所指的基类需要是一个单独的类。例如:

class Base():
    def layout(self):
        self.grid(row=0, column=0)
        self.config(bg="blue")

class MyLabels(Base, tk.Label):
    def __init__(self, parent, text, **kwargs):
        tk.Label.__init__(self, parent, text=text)
        self.layout(self, **kwargs)

class MyButtons(Base, tk.Button):
    def __init__(self, parent, text, command, **kwargs):
        tk.Button.__init__(self, parent, text=text, command=command)
        self.layout(self, **kwargs)

这种类型的类有时被称为mixin,因为它不是作为独立对象实例化的。相反,它“混合”了其他类的一些额外行为。mixin通常会有方法,但不会有自己的
\uuuuu init\uuuu

你知道为什么它被认为是对过程编程的改进吗?同样的想法也适用于这里。谢谢你,这让事情变得非常清楚!特别是你对我的第一句话的回应。把它和一个数学方程相比,真的给我画了一幅图画。关于我应该如何处理方法布局的建议,我觉得第二个选项更适合我的实际程序。我不太清楚到底该怎么做,但我会把它弄得一团糟,看看我能想出什么办法。再次感谢您的全面回答。我对您的回答补充了更多内容。我希望代码是按照您的建议重新编写的,但我似乎无法理解最后这些小障碍。如果您有更多的意见,我将不胜感激。我终于尝试了,效果非常好。这将使我的代码更加清晰易读。谢谢你的帮助!