Tkinter类结构(每帧类)与小部件复制有关 [英] Tkinter Class structure (class per frame) issue with duplicating widgets

查看:63
本文介绍了Tkinter类结构(每帧类)与小部件复制有关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试将OOP与Tkinter一起使用-我正在慢慢到达那里(我认为)...

Ive been trying out OOP for use with Tkinter - Im getting there (I think) slowly...

我想建立一个处理每个帧的结构按其自己的类,包括其所有小部件和功能。也许我从错误的角度出发,但这对我来说是最合乎逻辑的。 -随时告诉我您是否同意!

I wanted to build a structure where each frame is handled by its own class, including all of its widgets and functions. Perhaps I am coming from the wrong angle but that is what makes most logical sense to me. - Feel free to tell me if you agree / disagree!

我知道问题出在什么地方-当我将每个类都称为我的 __ init __ 每次运行并构建相关的小部件,无论它们是否已存在于框架中。但是,我能想到的唯一方法是在主类 GUI_Start __ init __ 中构建每个框架c>。 -尽管这看起来像是一个杂乱无章的解决方案。

I know why the problem is happening - when im calling each class my __init__ runs everytime and builds the relevant widgets regardless of whether they are already present in the frame. However, the only way I can think of getting round this would be to build each frame in the __init__ of my primary class GUI_Start. - Although this seems like a messy and un-organised soloution to the problem.

有没有一种方法可以使每个类都负责自己的功能和小部件,但不必每次都构建框架?

Is there a way I can achieve a structure where each class takes care of its own functions and widgets but doesn't build the frame each time?

请参阅以下问题的最小示例:

See below for minimal example of the issue:

from Tkinter import *

class GUI_Start:

    def __init__(self, master):
        self.master = master
        self.master.geometry('300x300')
        self.master.grid_rowconfigure(0, weight=1)
        self.master.grid_columnconfigure(0, weight=1)
        self.win_colour = '#D2B48C'
        self.frames = {}

        for window in ['win1', 'win2']:
            frame = Frame(self.master, bg=self.win_colour, bd=10, relief=GROOVE)
            frame.grid(row=0, column=0, sticky='news')
            setattr(self, window, frame)
            self.frames[window] = frame

        Page_1(self.frames)

    def Next_Page(self, frames, controller):
        controller(frames)


class Page_1(GUI_Start):

    def __init__(self, master):
        self.master = master
        self.master['win1'].tkraise()

        page1_label = Label(self.master['win1'], text='PAGE 1')
        page1_label.pack(fill=X)

        page1_button = Button(self.master['win1'], text='Visit Page 2...', command=lambda: self.Next_Page(self.master, Page_2))
        page1_button.pack(fill=X, side=BOTTOM)


class Page_2(GUI_Start):

    def __init__(self, master):
        self.master = master
        self.master['win2'].tkraise()

        page2_label = Label(self.master['win2'], text='PAGE 2')
        page2_label.pack(fill=X)

        page2_button = Button(self.master['win2'], text='Back to Page 1...', command=lambda: self.Next_Page(self.master, Page_1))
        page2_button.pack(fill=X, side=BOTTOM)


root = Tk()
gui = GUI_Start(root)
root.mainloop()

请随意批评我的结构

任何反馈将不胜感激!
Luke

Any feedback would be much appreciated! Luke

推荐答案

使用类的目的是将一堆行为封装为一个单元。对象不应修改自身以外的任何内容。至少不是简单地创建对象,而是可以有可能产生副作用的方法。

The point of using classes is to encapsulate a bunch of behavior as a single unit. An object shouldn't modify anything outside of itself. At least, not by simply creating the object -- you can have methods that can have side effects.

在我看来,创建页面的正确方法是:从 Frame 继承。属于页面的所有小部件都必须具有对象本身作为其父对象。例如:

In my opinion, the proper way to create "pages" is to inherit from Frame. All of the widgets that belong to the "page" must have the object itself as its parent. For example:

class PageOne(tk.Frame):
    def __init__(self, parent):
        # use the __init__ of the superclass to create the actual frame
        tk.Frame.__init__(self, parent)

        # all other widgets use self (or some descendant of self)
        # as their parent

        self.label = tk.Label(self, ...)
        self.button = tk.Button(self, ...)
        ...

完成后,您可以将此类的实例视为单个小部件:

Once done, you can treat instances of this class as if they were a single widget:

root = tk.Tk()
page1 = PageOne(root)
page1.pack(fill="both", expand=True)

您也可以创建基础 Page 类,并且如果您的所有页面都有一些共同点(例如,页眉或页脚),则让您的实际页面继承该类

You can also create a base Page class, and have your actual pages inherit from it, if all of your pages have something in common (for example, a header or footer)

class Page(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        <code common to all pages goes here>

class PageOne(Page):
    def __init__(self, parent):
        # initialize the parent class
        Page.__init__(self, parent)

        <code unique to page one goes here>

这篇关于Tkinter类结构(每帧类)与小部件复制有关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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