1

Tkinter GUI で一連のサブフレームを作成しようとしています。各サブフレームには、後で各サブフレームの一意の ID を介して取得できるようにする必要があるいくつかのユーザー入力変数が含まれています。サブフレームを自由に追加および削除し、適切な順序で ID を付けられるようにする必要があります (現時点では、整数は 1 からカウントアップします)。

本当に3つの質問:

1) 具体的には、各フレームのタイトルを表示するラベル ウィジェットが表示されないのはなぜですか? (これはおそらくばかげたことです...)

2) 特に、フレームを追加または削除するのに追加または削除ボタンを 2 回押す必要があるのはなぜですか?

3)一般的に:これにアプローチするより良い方法はありますか?フレームインスタンスを追跡するという意味で。それらは今リストにあります...私は以前に口述で始めましたが、それを扱うのは難しかったです...より良い提案はありますか?

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

ありがとう... :)

4

1 に答える 1

1

これが私がすることです:

  1. AllInstancesから継承します (「 FrameGroup Frame」などに名前を変更します)。その後、サブフレームが直接制御できる子である「メガウィジェット」になります。
  2. サブフレームを のサブクラスにしますFrame(そしてそれを「サブフレーム」と呼びます)。これも「メガウィジェット」であり、その親に疎結合する必要があります (つまり、root.all_instances
  3. 追加ボタンと削除ボタンで FrameGroup オブジェクトのメソッドを呼び出すようにします。

また、グローバル インポートを行わないことをお勧めします。ttk と tkinter の両方を使用しているため、インポート ステートメントの順序に応じて、一方が他方を上書きします。

これらの変更を加えた実際の例を次に示します。

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()
于 2013-09-25T15:55:14.737 に答える