问题描述
我尝试创建的其中一个按钮未正确显示在窗口中.我一直在努力学习OOP,所以我现在对它的理解非常基本,提前道歉.
One of the buttons i'm trying to create is not appearing correctly in the window. I've been trying to learn OOP, so my understanding of it is very basic right now, apologies in advance.
提交"按钮未正确显示.
The "Submit" button isn't appearing properly.
这是目前的代码:
class Window(Frame):
def __init__(self, master):
super().__init__()
self.master = master
master.title('Learning Python')
master.configure(background='black')
master.geometry('900x200')
master.resizable(0, 0)
class Submit(Button):
def __init__(self, master):
super().__init__()
self.master = master
Button(text='Submit', background='black', foreground='light green', highlightthickness=0,
border=0)
Button.pack(self)
class ProgressBar(ttk.Progressbar):
def __init__(self, master):
super().__init__()
self.master = master
progress_bar = ttk.Progressbar(orient='horizontal')
progress_bar.pack(fill=tk.BOTH)
class PagesRead(Label):
def __init__(self, master):
super().__init__()
self.master = master
pages_label = Label(text='How many page(s) did you read?', background='black', foreground='light green')
pages_label.pack()
class EntryBox(Entry):
def __init__(self, master):
super().__init__()
self.master = master
Entry(master)
Entry.pack(self)
if __name__ == '__main__':
root = tk.Tk()
app = Window(root)
bar = ProgressBar(root)
pages = PagesRead(root)
entry = EntryBox(root)
submit = Submit(root)
app.mainloop()
推荐答案
如果您正在尝试学习 OOP,那么您正在通过此代码学习坏习惯.
If you're trying to learn OOP, you're learning bad habits with this code.
我们来看看这段代码:
class Submit(Button):
def __init__(self, master):
super().__init__()
self.master = master
Button(text='Submit', background='black', foreground='light green', highlightthickness=0,
border=0)
Button.pack(self)
首先,因为你继承自Button
,这个类是一个Button
.然后你调用 Button(text=...)
来创建另一个按钮,所以现在你有两个.如果您要从其他某个类继承,则无需创建该类的第二个实例.
First, because you inherit from Button
, this class is a Button
. You then call Button(text=...)
which creates another button, so now you have two. If you're going to inherit from some other class, you don't need to create a second instance of that same class.
另外,这两行是错误的:
Also, these two lines are wrong:
super().__init__()
self.master = master
您需要将master
传递给超类的__init__
.master 不仅仅是一个属性,它是小部件定义的一个组成部分.它会影响小部件的显示方式.它必须传递给超类,以便小部件正确初始化.
You need to pass master
to the __init__
of the superclass. The master is more than just an attribute, it's an integral part of the definition of the widget. It affects how the widget will appear. It must be passed to the superclass in order for the widget to be properly initialized.
此外,这有点主观,但您不应该从 Submit
的定义中调用 Button.pack(self)
.对象的主要原因之一是制作可重用的组件.通过在自身上调用小部件 pack
(或 grid
或 place
)严重限制了它的可重用性.通过在 Submit
中调用 pack
,它可以防止您使用它或将其移动到使用 grid
的 UI 中的其他位置.这是一个不必要的限制.
Also, this is slightly more subjective, but you should not be calling Button.pack(self)
from within the definition of Submit
. One of the main reasons for objects is to make reusable components. By having a widget call pack
(or grid
or place
) on itself severely limits its re-usability. By calling pack
inside Submit
, it prevents you from using it or moving it to some other location in your UI which uses grid
. That is an unnecessary constraint.
根据我的经验,UI 的整体布局会在开发过程中发生变化.如果您决定要从 pack
切换到 grid
,因为您已设计更改布局怎么办?按照您编写此代码的方式,您将不得不修改每个类.
In my experience, the overall layout of a UI will change during development. What if you decide that you want to switch from pack
to grid
because you've designed to change the layout? The way you have written this code, you will have to modify every single class.
相反,创建小部件的代码应该负责调用pack
、grid
或place
.这意味着将调用移到类之外并移到实例化类的代码中.这样,如果您选择使用 grid
,或者继续使用 pack
但使用一些额外的框架进行组织,您只需更改创建每个小部件的一个函数,而不是而不必更改每个小部件本身.
Instead, code that creates a widget should be responsible for calling pack
, grid
, or place
. That means moving the call outside of the class and into the code that instantiates the class. This way, if you choose to use grid
, or stay with pack
but use some extra frames for organization, you only have to change the one function that creates each widget, rather than having to change every widget itself.
例如,Submit
按钮类应该更像这样:
For example, the Submit
button class should more look like this:
class Submit(Button):
def __init__(self, master):
super().__init__(master)
self.configure(text='Submit', background='black', foreground='light green',
highlightthickness=0, border=0)
然后,在创建它的相同代码中,这就是您调用 pack 的地方
Then, in the same code where it's created, that's where you call pack
submit = Submit(root)
...
submit.pack(...)
如果您后来决定切换到 grid
,您需要更改的只是最后一个代码块.
If you later decide to switch to grid
, all you have to change is that last block of code.
这篇关于使用 tkinter 创建一个简单的 GUI,但有一个小问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!