试图掌握将框架和小部件放在tkinter类中的要点 [英] Trying to grasp the point of putting frames and widgets in classes for tkinter

查看:83
本文介绍了试图掌握将框架和小部件放在tkinter类中的要点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

As the question states, I can't seem to fully grasp the point of using classes with tkinter.

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

I have read through a decent number of different sites but I keep getting search results on how to create and use classes, but none so far have been able to get through to me. I've even scoured through the suggested questions while asking this one. The closest I've come to understanding is Bryan's explanation on this answer to the question Why use classes when programming a tkinter gui?

但仍然,我觉得我已经快要了,只是还远远不够理解.

But still, I feel like I'm almost there, just not quite over the edge of understanding.

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

In his example in the link, he creates an unconventional program, and then a better, more conventional program that does the same thing. I know that it represents a much smaller scale than the thousand-line programs that could really benefit from an object oriented approach.

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

Does every widget need to be in its own separate frame that's maybe part of an even bigger frame?

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

Can classes have methods that create and place a frame? In addition, can those same classes have methods than can create, modify, and place a widget within the previously made frame?

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

I also have some code that allows me to create, modify, and place a widget. Although I know it's not conventional, so I would greatly appreciate some input on this as well. Any suggestions on what you would do with this code to make it better?

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()


在评论后 因此,从昨天开始,我已经工作了许多小时,试图结合您对我的想法.这是我想出的:


Edited after comments: So I've been working many hours since yesterday trying to incorporate the ideas you've had for me. This is what I came up with:

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()放在子类中.

I've tried moving things around and rewriting lots of areas on this little side program, and even though I was able to prove that btn is infact accessing the self.config(bg="blue") attribute, the button doesn't appear to change. As a matter of fact I can't find a way to make the button appear without needing to put self.grid() in the child class just after the button is created.

尽管如此,即使我确实添加了self.grid(),该按钮仍然不会变成蓝色. self有问题吗?

Still, even if I did add the self.grid() the button still won't turn blue. Is it something with self?

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

Why won't the button appear when the child class creates it, and the parent class places it?

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

Note: I've purposefully omitted the entire layout function and replaced it with just a simple config method. I figure if I can understand this, I can then find a way to incorporate the whole function back into the code.

推荐答案

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

Does every widget need to be in its own separate frame that's maybe part of an even bigger frame?

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

That's a bit like asking if every part of a mathematical expression needs parenthesis. Strictly speaking, the answer is "no". However, using frames to organize groups of widgets is a tool designed to make writing and understanding the code easier, much like parenthesis in a complex math equation makes writing and understanding the equation easier.

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

Can classes have methods that create and place a frame? In addition, can those same classes have methods than can create, modify, and place a widget within the previously made frame?

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

Yes, and yes. Methods in a class don't have any limitations on what they can and cannot do. Methods of a class can do anything that a normal function can do.

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

I also have some code that allows me to create, modify, and place a widget. Although I know it's not conventional, so I would greatly appreciate some input on this as well. Any suggestions on what you would do with this code to make it better?

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

"Better" is highly subjective. What is better for 20 lines of code might not be better for 200, 2,000, or 20,000. What is better for a function used exactly twice might not be better for a function used hundreds or thousands of times (or visa versa).

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

That being said, you're doing one thing that is very unconventional and which leads to making your code harder to understand: you're using self as a parameter for a function that is not a method of a class. self means something very specific to python programmers; using it outside of the context of a method is very confusing.

您应该对方法layout做以下两件事之一:

You should do one of two things for the method layout:

  • self重命名为widgetself以外的任何其他术语
  • 创建一个定义layout的基类,然后让您的类从该基类继承.在这种情况下,self是正确的第一个参数.
  • Rename self to be widget or any other term other than self
  • Create a base class that defines layout, and then have your classes inherit from the base class. In that case, self is the proper first argument.

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

This part of the answer refers to code which was added after I wrote my original answer.

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

The base class I was referring to needs to be a separate class. For example:

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通常具有方法,但不会具有自己的__init__.

This type of class is sometimes called a mixin because it's not designed to be instantiated as a standalone object. Rather, it "mixes in" some additional behavior to other classes. A mixin will typically have methods, but won't have its own __init__.

这篇关于试图掌握将框架和小部件放在tkinter类中的要点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆