小编典典

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

python

正如问题所指出的,我似乎无法完全掌握在tkinter中使用类的意义。

我已经阅读了许多不同的网站,但是我一直在搜索有关如何创建和使用类的搜索结果,但是到目前为止,还没有任何一个能与我联系。在询问这一问题时,我什至已经仔细研究了建议的问题。我最了解的是布莱恩(Bryan)对这个问题的答案的解释,该问题为什么在编写tkinter
gui时使用类?

但是,我仍然觉得自己快到 ,只是还不完全理解。

在该链接的示例中,他创建了一个非常规程序,然后创建了一个执行相同功能的更好,更常规的程序。我知道它所代表的规模要比千行程序小得多,后者可以真正受益于面向对象的方法。

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

类可以具有创建和放置框架的方法吗?另外,那些相同的类是否具有比在先前制作的框架中创建,修改和放置小部件的方法更多的方法?

我也有一些代码可以让我创建,修改和放置小部件。尽管我知道这不是常规做法,所以我也将不胜感激。关于如何使用此代码以使其变得更好的任何建议?

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()了按钮,按钮也不会变成蓝色。有东西self吗?

为什么在子类创建按钮并将其放置在父类上时按钮不出现?

注意:我特意省略了整个layout function内容,仅将其替换为一个简单的内容config method。我认为,如果我能理解这一点,那么我便可以找到一种将整个功能重新整合到代码中的方法。


阅读 138

收藏
2021-01-20

共1个答案

小编典典

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

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

类可以具有创建和放置框架的方法吗?另外,那些相同的类是否具有比在先前制作的框架中创建,修改和放置小部件的方法更多的方法?

是的,是的。类中的方法对其可以做什么和不可以做什么没有任何限制。类的方法可以执行普通函数可以执行的任何操作。

我也有一些代码可以让我创建,修改和放置小部件。尽管我知道这不是常规做法,所以我也将不胜感激。关于如何使用此代码以使其变得更好的任何建议?

“更好”是高度主观的。对于20行代码而言,更好的选择对于200、2,000或20,000可能不会更好。对于仅使用两次的功能而言,更好的方法可能对于使用数百或数千次的功能却未必更好(反之亦然)。

话虽这么说,您正在做的事情非常不常规,导致您的代码难以理解:您将其self用作不是类方法的函数的参数。self表示某些特定于python程序员的东西;在方法上下文之外使用它非常令人困惑。

您应该为该方法做两件事之一layout

  • 重命名selfwidget或除self
  • 创建定义的基类,layout然后让您的类从基类继承。在这种情况下,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通常会有方法,但不会有方法__init__

2021-01-20