Python — tkinter — динамические флажки

#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() для его скрытия.