簡體   English   中英

Tkinter 從按鈕動態創建小部件

[英]Tkinter dynamically create widgets from button

我正在嘗試制作一個動態 GUI,單擊一個按鈕會導致創建一個新框架,該框架放置在按鈕上方,其中包含 3 個條目小部件(用戶選項),我需要能夠從中讀取用戶輸入3 個條目小部件並可能更改它們。 每次按下按鈕時,都會出現三個新的可調用條目小部件。

我知道這是錯誤的,因為它一直給我錯誤,但是可以使用類似於列表的東西來動態創建小部件嗎?

from Tkinter import *

app = Tk()

frameNames = []
widgetNames = []

def createwidgets():
    global widgetNames
    global frameNames
    frameNames += (str("g"+str(len(frameNames))))  #why does the letter & number get added as seperate elements?
    widgetNames += [(str("w"+str(len(widgetNames)-1))), 
                    (str("w"+str(len(widgetNames)))),    
                    (str("w"+str(len(widgetNames)+1)))]

    frameNames[len(frameNames) - 1] = Frame(app)
    frameNames[len(frameNames) - 1].pack()

    widgetNames[len(widgetNames) - 3] = Entry(frameNames[len(frameNames) - 1])
    widgetNames[len(widgetNames) - 3].pack()
    widgetNames[len(widgetNames) - 2] = Entry(frameNames[len(frameNames - )- 1])
    widgetNames[len(widgetNames) - 2].pack()
    widgetNames[len(widgetNames) - 1] = Entry(frameNames[len(frameNames) - 1])
    widgetNames[len(widgetNames) - 1].pack()

createWidgetButton = Button(app, text="createWidgets", command=createwidgets())
createWidgetButton.grid(sticky=S)

app.mainloop()

主要問題是這四行代碼:

frameNames[len(frameNames) - 1] = Frame(app)
frameNames[len(frameNames) - 1].pack()
...
createWidgetButton = Button(app, text="createWidgets", command=createwidgets())
createWidgetButton.grid(sticky=S)

您將 frame 和 button 創建為app的子項,但您使用grid為一個使用pack為另一個使用pack 你必須與app所有直系后代保持一致——他們必須都使用pack或者他們必須都使用grid

第二個問題是這一行:

frameNames += (str("g"+str(len(frameNames))))  #why does the letter & number get added as seperate elements?

在這里, frameNames是一個列表,您正在嘗試使用字符串添加它。 添加與附加不同。 您需要在添加新名稱之前附加新名稱,或將新名稱放入臨時列表中。

frameNames.append(str(...))

第三個問題是這一行:

createWidgetButton = Button(app, text="createWidgets", command=createwidgets())

上面的和這個完全一樣:

result = createWidgets()
createWidgetButton = Button(app, text="createWidgets", command=result)

您必須傳遞對函數的引用,而不是調用該函數。 將行更改為此(注意createWidgets之后缺少括號):

createWidgetButton = Button(app, text="createWidgets", command=createwidgets)

與問題無關,但如果您使用臨時變量而不是重復模式(str("w"+str(len(widgetNames)-1) ,您的代碼會容易閱讀。正如所寫,您的代碼幾乎不可能閱讀。此外,您不想存儲小部件名稱,您需要存儲實際的小部件本身。

最后,不要進行通配符導入。 根本沒有充分的理由這樣做。

以下是我將如何重寫您的代碼:

import Tkinter as tk

app = tk.Tk()

frames = []
widgets = []

def createwidgets():
    global widgetNames
    global frameNames

    frame = tk.Frame(app, borderwidth=2, relief="groove")
    frames.append(frame)

    frame.pack(side="top", fill="x")

    for i in range(3):
        widget = tk.Entry(frame)
        widgets.append(widget)

        widget.pack(side="left")

createWidgetButton = tk.Button(app, text="createWidgets", command=createwidgets)
createWidgetButton.pack(side="bottom", fill="x")

app.mainloop()

這個比較簡單。

我們可以通過創建一個Frame小部件而不是打包它來做到這一點,用我們需要的任何東西填充它,然后讓一個Button調用Frame小部件上的包。

很像下面的:

from tkinter import *

class App:
    def __init__(self, root):
        self.root = root
        self.create = Button(self.root, text="Create", command=self.draw)
        self.create.pack(side="bottom")
        self.frame = Frame(self.root)
        self.entry1 = Entry(self.frame)
        self.entry2 = Entry(self.frame)
        self.entry3 = Entry(self.frame)
        self.entry1.pack()
        self.entry2.pack()
        self.entry3.pack()
        self.submit = Button(self.frame, text="Submit", command=self.command)
        self.submit.pack()
    def draw(self):
        self.frame.pack(side="top")
    def command(self):
        print(self.entry1.get())
        print(self.entry2.get())
        print(self.entry3.get())

root = Tk()
App(root)
root.mainloop()

如果您需要添加多個這些表單,您可以執行以下操作,該操作使用匿名函數 ( lambda ) 以便擁有“知道”它們在哪個框架中的“自我感知”按鈕:

from tkinter import *

class App:
    def __init__(self, root):
        self.frames = []
        self.entries = []
        self.count = 0
        self.root = root
        self.create = Button(self.root, text="Create", command=self.draw)
        self.create.pack(side="bottom")
    def draw(self):
        self.frames.append(Frame(self.root, borderwidth=1, relief="solid"))
        self.frames[self.count].pack(side="top")
        self.entries.append([Entry(self.frames[self.count]), Entry(self.frames[self.count]), Entry(self.frames[self.count])])
        for i in self.entries[self.count]:
            i.pack()
        Button(self.frames[self.count], text="Submit", command=lambda c=self.count: self.submit(c)).pack()
        self.count += 1
    def submit(self, c):
        for i in self.entries[c]:
            print(i.get())

root = Tk()
App(root)
root.mainloop()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM