#python #user-interface #checkbox #tkinter #python-3.5
#python #пользовательский интерфейс #флажок #tkinter #python-3.5
Вопрос:
В одном из моих курсов была мимолетная ссылка на tkinter, и это выходило за рамки того, что предлагал вводный курс. Это вызвало мое любопытство, и я хотел копнуть глубже.
У меня есть основы — я могу заставить флажки появляться там, где я хочу, но я бы хотел сделать его более динамичным / pythonic.
Столбец 1 — все флажки должны отображаться всегда. Это работает, как и ожидалось. Столбец 2 — должен отображаться только первый флажок, и если он нажат, то должны отображаться дополнительные 4 флажка. При нажатии любого из этих 4 флажков должно отображаться сообщение в текстовом поле в нижней части пользовательского интерфейса.
Когда я нажимаю флажки для курсов фокусировки во 2-м столбце на данный момент, они ничего не делают. Кроме того, флажок ABC 702, который обычно скрыт, появляется случайным образом, когда установлен флажок для основного курса. Я не могу понять, почему.
from tkinter import *
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.create_widgets()
# self.grid()
# self.create_widgets()
def create_widgets(self):
Label(self, text="How many of the core courses have you completed so far?"
).grid(row=1, column=0, sticky=W)
self.checkBoxA = BooleanVar()
Checkbutton(self,
text="ABC 501",
variable=self.checkBoxA,
command=self.update_text
).grid(row=2, column=0, sticky=W)
self.checkBoxB = BooleanVar()
Checkbutton(self,
text="ABC 502",
variable=self.checkBoxB,
command=self.update_text
).grid(row=3, column=0, sticky=W)
self.checkBoxC = BooleanVar()
Checkbutton(self,
text="ABC 601",
variable=self.checkBoxC,
command=self.update_text
).grid(row=4, column=0, sticky=W)
self.checkBoxD = BooleanVar()
Checkbutton(self,
text="ABC 602",
variable=self.checkBoxD,
command=self.update_text
).grid(row=5, column=0, sticky=W)
self.checkBoxE = BooleanVar()
Checkbutton(self,
text="ABC 603",
variable=self.checkBoxE,
command=self.update_text
).grid(row=6, column=0, sticky=W)
self.checkBoxF = BooleanVar()
Checkbutton(self,
text="ABC 701",
variable=self.checkBoxF,
command=self.update_text
).grid(row=7, column=0, sticky=W)
self.results_txt = Text(self, width=80, height=10, wrap=WORD)
self.results_txt.grid(row=8, column=0, columnspan=3)
Label(self, text="Which focus are you enrolled in?"
).grid(row=1, column=1, sticky=W)
self.checkBoxF1 = BooleanVar()
Checkbutton(self,
text="Focus #1",
variable=self.checkBoxF1,
command=self.update_text
).grid(row=2, column=1, sticky=W)
# if self.checkBoxF1.get():
# self.checkBoxF1A = BooleanVar()
# Checkbutton(self,
# text="ABC 503",
# variable=self.checkBoxF1A,
# command=self.update_text
# ).grid(row=3, column=1, sticky=W)
def update_text(self):
courses = ""
counter = 0
focusCounter = 0
##The checkboxes for the focus courses do not display text at the bottom
##The ABC 702 checkbox randomly appears when clicking core courses
##Is this related to reusing self vs creating another attribute?
if self.checkBoxF1.get():
self.checkBoxF1A = BooleanVar()
Checkbutton(self,
text="ABC 503",
variable=self.checkBoxF1A,
command=self.update_text
).grid(row=3, column=1, sticky=W)
self.checkBoxF1B = BooleanVar()
Checkbutton(self,
text="ABC 504",
variable=self.checkBoxF1B,
command=self.update_text
).grid(row=4, column=1, sticky=W)
self.checkBoxF1C = BooleanVar()
Checkbutton(self,
text="ABC 505",
variable=self.checkBoxF1C,
command=self.update_text
).grid(row=5, column=1, sticky=W)
self.checkBoxF1D = BooleanVar()
Checkbutton(self,
text="ABC 702",
variable=self.checkBoxF1D,
command=self.update_text
).grid(row=6, column=1, sticky=W)
if self.checkBoxA.get():
courses = "Introductory class n"
counter = 1
if self.checkBoxB.get():
courses = "Next level class description n"
counter = 1
if self.checkBoxC.get():
courses = "Core class #3 n"
counter = 1
if self.checkBoxD.get():
courses = "Another core class n"
counter = 1
if self.checkBoxE.get():
courses = "A higher level class n"
counter = 1
if self.checkBoxF.get():
courses = "An advanced class n"
counter = 1
if self.checkBoxF1A.get():
specialty = "Focused class #1"
focusCounter = 1
if self.checkBoxF1B.get():
specialty = "Focused class #2"
focusCounter = 1
if self.checkBoxF1C.get():
specialty = "Focused class #3"
focusCounter = 1
if self.checkBoxF1D.get():
specialty = "Focused class #4"
focusCounter = 1
self.results_txt.delete(0.0, END)
self.results_txt.insert(0.0, courses)
if focusCounter > 0: #this means the user selected at least 1 focus course
self.results_txt.insert(0.0, specialty)
if counter == 6:
congrats = ("n Congratulations on completing all of your core courses! n n")
self.results_txt.insert(0.0, congrats)
# print(focusCounter)
root = Tk()
root.title("This is where the title goes")
app = Application(root)
root.mainloop()
Ответ №1:
Если вы сначала нажмете флажок Focus #1
, он покажет новые флажки, и они будут работать должным образом
Но если вы сначала установите другой флажок, то получите сообщение об ошибке
Ошибка атрибута: объект ‘Application’ не имеет атрибута ‘checkBoxF1A’
Проблема в том, что update_text()
вы используете checkBoxF1A
, checkBoxF1B
, и т.д., даже если они еще не существуют.
if self.checkBoxF1A.get():
specialty = "Focused class #1"
focusCounter = 1
Создайте self.checkBoxF1A = BooleanVar()
in create_widgets()
— не in if self.checkBoxF1.get()
, и у вас не будет проблем.
Вы даже можете создавать флажки без grid()
create_widgets()
self.checkbutton_F1 = Checkbuttons(...)
и if self.checkBoxF1A.get():
используется self.checkbutton_F1.grid(...)
для отображения виджета и (в else:
) self.checkbutton_F1.grid_forget()
для его скрытия.