#python-3.x #tkinter
#python-3.x #tkinter
Вопрос:
Я хочу написать всплывающее окно, в котором пользователю предлагается выбрать определенную опцию, и, если опция не существует, добавить ее. Однако у меня возникли проблемы с извлечением значения выбранной опции (то есть ключа из dict). Мой код — обобщен — пока:
import tkinter as tk
class Category():
def __init__(self):
self.categories = {1:"Coffee",2: "Tesco"}
def index(...):
# code ... #
root = tk.Tk()
v = tk.IntVar()
# I was thinking this would help:
def quit():
global irow
irow = v.get()
print("Irow is",irow)
root.quit()
tk.Label(root, text="Choose category:").pack()
for key, cat in self.categories.items():
tk.Radiobutton(root, text=cat, variable=v, value=key).pack()
tk.Radiobutton(root, text="Other", variable=v, value=key 1).pack()
# I want to add a text box here so user can add the "Other"
tk.Button(root, text="Close", command=quit)
irow = v.get()
print(irow)
root.mainloop()
print(irow)
# code which uses irow #
Выполнение этого кода приводит:
0
Irow is 0
0
независимо от того, какую кнопку я выбираю. Я ожидаю, что irow будет равен 2, если я должен был выбрать Tesco или 1, если я выбрал coffee (или 3, если я выбрал other). Любые рекомендации были бы очень признательны.
Ответ №1:
Как правило, mainloop
завершается только после уничтожения всех виджетов. Следовательно, на данном этапе вы не можете напрямую получать значения из виджетов. Самое простое решение — сохранить значение в глобальной переменной или переменной экземпляра, если вы используете классы.
Например, в вашем случае вы могли бы сделать это:
def quit():
self.irow = v.get()
root.quit()
Затем, после mainloop
существования, вы можете получить доступ self.irow
...
root.mainloop()
print(self.irow)
Комментарии:
1. Спасибо. Это работает, но каким-то образом значение v по-прежнему не обновляется, как только я делаю выбор. То есть по умолчанию оно остается равным 0. Есть идеи, почему это может быть?
2. @Erik: Я не знаю. Когда я исправил ошибки в вашем коде, он правильно напечатал элемент, который я выбрал после того, как я нажал на кнопку «Закрыть». Это, кажется, доказывает, что он действительно обновляется.
3. Интересно. Idle действительно показывает мне правильный ключ, не закрывая диалоговое окно, в то время как терминал закрывает диалоговое окно, но не дает мне правильный ключ.
Ответ №2:
Спасибо Брайану Оукли за ответ. Я внес 4 изменения, чтобы она работала на терминале Linux: 1) Я изменил класс с Tk () на Toplevel(); 2) Я поместил диалоговое окно в класс для чистоты; 3) Я изменил self.quit() на self.destroy(); amp; 4) Я изменил mainloop () на wait_window().
class AddCategory(tk.Toplevel):
def __init__(self, parent):
tk.Toplevel.__init__(self)
self.v = tk.IntVar()
self.parent = parent
tk.Label(self, text="Choose category:").pack()
for key, cat in self.parent.categories.items():
tk.Radiobutton(self, text=cat, variable=self.v, value=key).pack()
tk.Radiobutton(self, text="Other", variable=self.v, value=key 1).pack()
self.e = tk.Entry(self,text="")
self.e.pack()
tk.Button(self, text="Close", command=self.quit).pack()
def quit(self):
self.parent.key = self.v.get()
self.parent.cat = self.e.get()
print(self.v.get())
print(self.e.get())
self.destroy()
Обратите внимание, что parent — это класс, из которого я выполняю диалог «AddCategory». Я вызываю его следующим образом:
class Category():
def __init__(self):
self.cat = self.key = self.desc = []
self.categories = {1:"Coffee",2: "Tesco"}
self.descriptions = {}
def index(...):
# code ... #
dialog = AddCategory(self) # I pass the parent onto the dialog
dialog.wait_window()
print(self.key)
print(self.cat)
Это работает, потому что self.parent внутри AddCategory является программной копией parent.