什么是初始化 tkinter 类的父/主? [英] What is a parent/master that initialize a tkinter class?

查看:56
本文介绍了什么是初始化 tkinter 类的父/主?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

示例代码是精简版,但可以运行基本功能.请关注class MainWindow(tk.Frame)

The example code is an abridged version but can run with a basic function. Please focus on class MainWindow(tk.Frame)

什么样的object可以起到tkinter类初始化的parent或master的作用?

What kind of object can play the role of the parent or master for tkinter class initialization?

在我的情况下,请参见示例代码,为什么不能将 self 作为 parent 传递给 ProjectInfo(...)ConfirmItems(...)class MainWindow(tk.Frame) 中?如果使用 self 而不是 self.parent,它会弹出一个空窗口.

In my case, see the example code, why can not pass self as parent to ProjectInfo(...) or ConfirmItems(...) in class MainWindow(tk.Frame)? It would pop up an empty window if using self instead of self.parent.

这个问题源于我对 Best way to structure a tkinter application 的评论,这意味着它无法通过 self 作为 .

This question originates from my comments on Best way to structure a tkinter application, which means it fails to pass self as parent.

我想提出一个新问题来跟进讨论.

I would like to issue a new question to follow that discussions.

import tkinter as tk
from tkinter import messagebox
from collections import OrderedDict

class ProjectInfo(tk.Frame):
    def __init__(self, parent, controller, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        self.controller = controller
        self.widgets_init()

    def widgets_init(self):
        tk.Label(self,
                    text = "Rock Controller!",
                    width = 10,
                    anchor = "w",
                    justify = "left").grid(row = 0, column = 0)
        tk.Label(self,
                    text = "Input Name: ").grid(row = 1, column = 0)
        self.entry = tk.Entry(self)
        self.entry.grid(row = 1, column = 1)

class ConfirmItems(tk.Frame):
    def __init__(self, parent, frames, controller, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        self.frames = frames
        self.controller = controller
        self.widgets_init()

    def update_entries(self):
        self.controller.project_info.name = self.controller.project_info.entry.get()

    def update_frames(self):
        self.message = 'Click Cancel go back to reset!
'
        for key, values in self.frames.items():
            for v in values:
                x = getattr(key, v)
                self.message += v + ': ' + str(x) + '
'

    def show_settings(self):
        answer = tk.messagebox.askokcancel("Check Settings", self.message)
        if answer in ["yes", 1]:
            self.quit()

    def combine_funcs(self, *funcs):
        def combined_func(*args, **kwargs):
            for f in funcs:
                f(*args, **kwargs)
        return combined_func

    def widgets_init(self):
        self.cancel = tk.Button(self,
                                text = "Cancel",
                                command = self.quit)
        self.cancel.grid(row = 0, column = 0)

        self.submit = tk.Button(self,
                                text = "Submit",
                                command = self.combine_funcs(
                                                            self.update_entries,
                                                            self.update_frames,
                                                            self.show_settings))
                                # command = lambda:[self.update_frames(), self.show_settings()]
        self.submit.grid(row = 0, column = 1)

class MainWindow(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        self.controller = self

        self.project_info = ProjectInfo(self.parent, self.controller)
        self.project_info.grid(row = 0)
        self.widgets_init()

        self.confirm_items = ConfirmItems(self.parent, self.frames, self.controller)
        self.confirm_items.grid(row = 1)

    def widgets_init(self):
        self.dict_list = [(self.project_info, ('name',))]
        self.frames = OrderedDict(self.dict_list)

def main():
    root = tk.Tk()
    root.title("Welcome to Controller World!")
    root.geometry("300x300")
    gui = MainWindow(root)
    root.mainloop()

if __name__ == "__main__":
    main()

推荐答案

什么样的对象可以起到父类或主控的作用来进行tkinter类的初始化?

What kind of object can play the role of the parent or master for tkinter class initialization?

任何 tkinter 小部件都可以扮演父级或主控的角色,尽管它通常是根窗口、顶层窗口或框架.

Any tkinter widget can play the role of parent or master, though most often it will be the root window, a toplevel window, or a frame.

在我的情况下,请参阅示例代码,为什么不能将 self 作为父级传递给 MainWindow(tk.Frame) 类中的 ProjectInfo(...) 或 ConfirmItems(...)?

In my case, see the example code, why can not pass self as parent to ProjectInfo(...) or ConfirmItems(...) in class MainWindow(tk.Frame)?

您的代码中没有任何内容阻止您将 self 作为父级传递.

There is nothing in your code preventing you from passing self as the parent.

如果使用 self 而不是 self.parent 会弹出一个空窗口.

It would pop up an empty window if using self instead of self.parent.

在使用self作为ProjectInfo的parent的情况下,self指的是MainWindow的实例.我看不到您在该实例上调用 packgrid 的任何地方.如果父项不可见,则其子项均不可见.

In the case of using self as the parent for ProjectInfo, self refers to the instance of MainWindow. I don't see anywhere where you are calling pack or grid on that instance. If the parent is not visible, none of its children will be visible.

您需要在 gui 变量上调用 packgrid.由于它被设计为根窗口中的唯一小部件,因此 pack 最有意义.

You need to call pack or grid on the gui variable. Since it is designed to be the only widget in the root window, pack makes the most sense.

def main():
    ...
    gui = MainWindow(root)
    gui.pack(side="top", fill="both", expand=True)
    ...

<小时>

作为一般经验法则,如果您有一个从小部件继承的类并创建其他小部件,则这些小部件应始终是 self 或其后代之一的子级,而不是它自己的父母.让一个类将子小部件放在其父级中完全违背了从 tk.Frame 继承的目的.


As a general rule of thumb, if you have a class that inherits from a widget and it creates other widgets, those widgets should always be children of self or one of its descendants, never its own parent. Having a class put child widgets in its parent completely defeats the purpose of inheriting from tk.Frame.

tk.Frame 继承的全部意义在于创建一个行为与标准小部件完全相同的新类.您可以使用 packplacegrid 将其添加到其他小部件,它具有一些标准选项,例如 borderwidthrelief,并且是完全独立的.

The whole point of inheriting from tk.Frame is to create a new class that behaves exactly like standard widgets. You can add it to other widgets with pack or place or grid, it has some standard options such as borderwidth and relief, and is entirely self-contained.

这篇关于什么是初始化 tkinter 类的父/主?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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