添加和删​​除tkinter帧 - 跟踪实例

时间:2013-09-25 11:34:34

标签: python class tkinter instance

我正在尝试在Tkinter GUI中创建一堆子帧,每个子帧包含一些用户输入变量,我需要通过每个子帧的唯一ID来获取这些变量。我需要能够随意添加和删除子帧,并以合理的顺序对它们进行ID识别(此时整数从1开始计算)

真的有三个问题:

1)具体来说,为什么Label小部件显示每个帧的标题不显示? (这可能是愚蠢的......)

2)具体来说,为什么有时两次按下添加或删除按钮来添加或删除一个框架?

3)一般来说:有没有更好的方法来解决这个问题?在跟踪框架实例的意义上。他们现在在列表中...我之前开始使用dict但是更难以使用...是否有更好的建议?

from tkinter import *
from tkinter.ttk import *

class AllInstances(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.master_frame = Frame(self)
        self.master_frame.grid()
        self.all_instances = []

root = AllInstances()

class OneInstance():
    def __init__(self):
        self.number = len(root.all_instances) + 1

        var1 = StringVar()
        var2 = StringVar()
        var3 = StringVar()

        self.sub_frame = Frame(root.master_frame)
        self.sub_frame.grid(column = self.number, row = 0)

        titletext = StringVar()
        titletext.set('%s %s' % ('Frame', self.number))
        print(titletext.get())
        title = Label(self.sub_frame, textvariable = titletext)
        title.grid() #work out why this label does not display!

        uservar1 = Entry(self.sub_frame, textvariable = var1)
        uservar1.grid()
        uservar2 = Entry(self.sub_frame, textvariable = var2)
        uservar2.grid()
        uservar3 = Entry(self.sub_frame, textvariable = var3)
        uservar3.grid()
        #etc etc

        add_button = Button(self.sub_frame, text = 'Add', command = lambda: Create())
        add_button.grid()

        def RemoveInstance(self):
            if len(root.all_instances) > 1:
                root.all_instances.remove(self)
                self.sub_frame.destroy()

                for instance in root.all_instances:
                    instance.number = (root.all_instances.index(instance) + 1)
            else:
                pass

        remove_button = Button(self.sub_frame, text = 'Remove', command = lambda: RemoveInstance(self))
        remove_button.grid()

        root.all_instances.append(self)

def Create():
    OneInstance()

Create()
root.mainloop()

谢谢...:)

1 个答案:

答案 0 :(得分:0)

这就是我要做的事情:

  1. AllInstances继承自Frame(并重命名为“FrameGroup”之类的东西)。然后它变成一个“megawidget”,子帧是可以直接控制的子节点。
  2. 使您的子帧成为Frame的子类(并将其称为“子帧”)。这也是一个“megawidget”,它需要与其父级松散耦合(即:它不应该知道root.all_instances
  3. 让您的添加和删除按钮调用FrameGroup对象上的方法。
  4. 我还建议进行全局导入。由于您同时使用ttk和tkinter,因此根据您订购import语句的顺序,将覆盖另一个。

    这是一个包含这些修改的工作示例:

    import tkinter as tk
    
    class FrameGroup(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
            self.all_instances = []
            self.counter = 0
    
        def Add(self):
            self.counter += 1
            name = "Frame %s" % self.counter 
            subframe = Subframe(self, name=name)
            subframe.pack(side="left", fill="y")
            self.all_instances.append(subframe)
    
        def Remove(self, instance):
            # don't allow the user to destroy the last item
            if len(self.all_instances) > 1:
                index = self.all_instances.index(instance)
                subframe = self.all_instances.pop(index)
                subframe.destroy()
    
        def HowMany(self):
            return len(self.all_instances)
    
        def ShowMe(self):
            for instance in self.all_instances:
                print(instance.get())
    
    class Subframe(tk.Frame):
        def __init__(self, parent, name):
            tk.Frame.__init__(self, parent)
            self.parent = parent
            self.e1 = tk.Entry(self)
            self.e2 = tk.Entry(self)
            self.e3 = tk.Entry(self)
            label = tk.Label(self, text=name, anchor="center")
            add_button = tk.Button(self, text="Add", command=self.parent.Add)
            remove_button = tk.Button(self, text="Remove", command=lambda: self.parent.Remove(self))
    
            label.pack(side="top", fill="x")
            self.e1.pack(side="top", fill="x")
            self.e2.pack(side="top", fill="x")
            self.e3.pack(side="top", fill="x")
            add_button.pack(side="top")
            remove_button.pack(side="top")
    
        def get(self):
            return (self.e1.get(), self.e2.get(), self.e3.get())
    
    class GUI(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.master_frame = tk.Frame(self)
            self.master_frame.grid()
            self.all_instances = FrameGroup(self.master_frame)
            self.all_instances.grid()
    
            # create the first frame
            self.all_instances.Add()
    
    root = GUI()
    root.mainloop()