Tkinter динамически создает виджеты с кнопки

Вопрос: Я пытаюсь сделать динамический графический интерфейс, когда нажатие кнопки вызывает создание нового фрейма, который находится над кнопкой с 3 видными виджетами (пользовательскими параметрами) внутри нее, и мне нужно иметь возможность читать пользовательский ввод из 3 виджетов и, возможно, изменить их. Каждый раз, когда нажимается кнопка, появляются три новых вызываемых элемента входа. Я знаю, что

Вопрос:

Я пытаюсь сделать динамический графический интерфейс, когда нажатие кнопки вызывает создание нового фрейма, который находится над кнопкой с 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)

Вы создаете как фрейм, так и кнопку в качестве дочернего элемента app, но вы используете grid для одного и 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() Ответ №1

Это относительно просто.

Мы можем сделать это, создав виджет 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()

Оцените статью
Добавить комментарий