[Python] How to improve pack_forget() and pack() since they flicker the screen as widgets...

Discussão em 'Python' iniciado por Stack, Março 19, 2025.

  1. Stack

    Stack Membro Participativo

    I have a small app using tkinter/customtkinter. When I click a drop down (CTkOptionMenu) it chooses a form to display and all other forms become hidden:

    def show_selected_form(self, event):
    selected_name = self.form_selector.get()
    for name, form in self.forms.items():
    form.pack_forget()
    if selected_name:
    self.forms[selected_name].pack()


    This works however when I change the option in the menu, the app flickers with the creation of the widgets. I believe the .pack() option is the culprit. Is there another option so that the form/frame updates instantly?

    I have tried messing around with .after() and .update()/.update_idletasks() in different places but it feels like the visual flicker is when the form packs itself (theres several textboxes, checkboxes, labels, etc. that are part of each form)

    Here is a watered down recreation:

    Form1 + Form2

    import tkinter as tk
    import os
    import csv
    from tkinter import messagebox
    import customtkinter
    from ctkdatepicker import CTkDatePicker


    class Form2(customtkinter.CTkFrame):
    def __init__(self, parent):
    super().__init__(parent)

    self.csv_file = os.path.join(os.path.expanduser("~"), "Desktop", "csv2.csv")

    customtkinter.CTkLabel(self, text="Value1").grid(row=0, column=0, padx=5, pady=5)
    self.value1 = customtkinter.CTkEntry(self)
    self.value1.grid(row=0, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value2:").grid(row=1, column=0, padx=0, pady=0)
    self.value2 = customtkinter.CTkEntry(self)
    self.value2.grid(row=1, column=1, padx=0, pady=0)

    customtkinter.CTkLabel(self, text="Date1:").grid(row=2, column=0, padx=5, pady=5)
    self.date1 = customtkinter.CTkComboBox(self)
    self.date1.grid(row=2, column=1, padx=5, pady=5)
    CTkDatePicker(self.date1)
    self.date1.set("")

    customtkinter.CTkLabel(self, text="Value3:").grid(row=3, column=0, padx=0, pady=0)
    self.value3 = customtkinter.CTkEntry(self)
    self.value3.grid(row=3, column=1, padx=0, pady=0)

    submit_button = customtkinter.CTkButton(self, text="Submit", command=self.submit_form)
    submit_button.grid(row=10, columnspan=2, pady=5)

    def submit_form(self):
    value1 = self.value1.get()
    value2 = self.value2.get()
    date1 = self.date1.get()
    value3 = self.value3.get()

    file_exists = os.path.isfile(self.csv_file)
    with open(self.csv_file, 'a', newline='') as csvfile:
    writer = csv.writer(csvfile)
    if not file_exists:
    writer.writerow([
    'Value1', 'Value2', 'Value3', 'Value4', 'Value5',
    'Value6'
    ])
    writer.writerow([
    value1, value2, date1, value3, '', ''
    ])

    self.value1.delete(0, tk.END)
    self.value2.delete(0, tk.END)
    self.value3.delete(0, tk.END)
    self.date1.set("")

    messagebox.showinfo("Success", "Data submitted successfully!")


    import tkinter as tk
    import os
    import csv
    from tkinter import messagebox
    import customtkinter
    from ctkdatepicker import CTkDatePicker


    class Form1(customtkinter.CTkFrame):
    def __init__(self, parent):
    super().__init__(parent)

    self.csv_file = os.path.join(os.path.expanduser("~"), "Desktop", "csv.csv")

    customtkinter.CTkLabel(self, text="Value1:").grid(row=1, column=0, padx=5, pady=5)
    self.value1 = customtkinter.CTkEntry(self)
    self.value1.grid(row=1, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value2:").grid(row=2, column=0, padx=5, pady=5)
    self.value2 = customtkinter.CTkEntry(self)
    self.value2.grid(row=2, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value3:").grid(row=3, column=0, padx=5, pady=5)
    self.value3 = customtkinter.CTkEntry(self)
    self.value3.grid(row=3, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value4:").grid(row=4, column=0, padx=5, pady=5)
    self.value4 = customtkinter.CTkEntry(self)
    self.value4.grid(row=4, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value5:").grid(row=5, column=0, padx=5, pady=5)
    self.value5 = customtkinter.CTkEntry(self)
    self.value5.grid(row=5, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value6:").grid(row=6, column=0, padx=5, pady=5)
    self.value6 = customtkinter.CTkEntry(self)
    self.value6.grid(row=6, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value7:").grid(row=7, column=0, padx=5, pady=5)
    self.value7 = customtkinter.CTkEntry(self)
    self.value7.grid(row=7, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value8:").grid(row=8, column=0, padx=5, pady=5)
    self.value8 = customtkinter.CTkEntry(self)
    self.value8.grid(row=8, column=1, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value9:").grid(row=1, column=3, padx=5, pady=5)
    self.value9 = customtkinter.CTkEntry(self)
    self.value9.grid(row=1, column=4, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value10:").grid(row=2, column=3, padx=5, pady=5)
    self.value10 = customtkinter.CTkEntry(self)
    self.value10.grid(row=2, column=4, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value11:").grid(row=3, column=3, padx=5, pady=5)
    self.value11 = customtkinter.CTkEntry(self)
    self.value11.grid(row=3, column=4, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Value12:").grid(row=4, column=3, padx=5, pady=5)
    self.value12 = customtkinter.CTkEntry(self)
    self.value12.grid(row=4, column=4, padx=5, pady=5)

    self.choice_options = ["Choice 1", "Choice 2", "Choice 3", "Choice 4"]
    self.selected_choice = customtkinter.StringVar()
    self.selected_choice.set(self.choice_options[3])
    self.selected_choice_combobox = customtkinter.CTkComboBox(self, values=self.choice_options,
    variable=self.selected_choice, state="readonly")
    customtkinter.CTkLabel(self, text="Choice1:").grid(row=5, column=3, padx=5, pady=5)
    self.selected_choice_combobox.grid(row=5, column=4, padx=5, pady=5)

    customtkinter.CTkLabel(self, text="Date1:").grid(row=6, column=3, padx=5, pady=5)
    self.date1 = customtkinter.CTkComboBox(self)
    self.date1.grid(row=6, column=4, padx=5, pady=5)
    CTkDatePicker(self.date1)
    self.date1.set("")

    customtkinter.CTkLabel(self, text="Date2:").grid(row=7, column=3, padx=5, pady=5)
    self.date2 = customtkinter.CTkComboBox(self)
    self.date2.grid(row=7, column=4, padx=5, pady=5)
    CTkDatePicker(self.date2)
    self.date2.set("")

    customtkinter.CTkLabel(self, text="Date3:").grid(row=8, column=3, padx=5, pady=5)
    self.date3 = customtkinter.CTkComboBox(self)
    self.date3.grid(row=8, column=4, padx=5, pady=5)
    CTkDatePicker(self.date3)
    self.date3.set("")

    self.checkbox1 = customtkinter.IntVar()
    customtkinter.CTkCheckBox(self, text="CheckBox 1", variable=self.checkbox1).grid(row=9, column=0, padx=5, pady=5, sticky="w")

    self.checkbox2 = customtkinter.IntVar()
    customtkinter.CTkCheckBox(self, text="CheckBox 2", variable=self.checkbox2).grid(row=10, column=0, padx=5, pady=5, sticky="w")

    self.checkbox3 = customtkinter.StringVar(value="TRUE")
    customtkinter.CTkCheckBox(self, text="CheckBox 3", variable=self.checkbox3, onvalue="TRUE", offvalue="FALSE").grid(row=9, column=3, padx=5, pady=5, sticky="w")

    customtkinter.CTkLabel(self, text="Date4:").grid(row=10, column=3, padx=5, pady=5)
    self.date4 = customtkinter.CTkComboBox(self)
    self.date4.grid(row=10, column=4, padx=5, pady=5)
    CTkDatePicker(self.date4)
    self.date4.set("")

    customtkinter.CTkLabel(self, text="Notes:").grid(row=1, column=5, padx=5, pady=5)
    self.entry_notes = customtkinter.CTkTextbox(self, width=300, height=200, wrap="word")
    self.entry_notes.grid(row=0, column=6, rowspan=7, padx=5, pady=5, sticky="n")

    submit_button = customtkinter.CTkButton(self, text="Submit", command=self.submit_form)
    submit_button.grid(row=11, columnspan=2, pady=5)

    def submit_form(self):
    value1 = self.value1.get()
    value2 = self.value2.get()
    value3 = self.value3.get()
    value4 = self.value4.get()
    value5 = self.value5.get()
    value6 = self.value6.get()
    value7 = self.value7.get()
    value8 = self.value8.get()
    value9 = self.value9.get()
    value10 = self.value10.get()
    value11 = self.value11.get()
    value12 = self.value12.get()
    choice = self.selected_choice.get()
    date1 = self.date1.get()
    date2 = self.date2.get()
    date3 = self.date3.get()
    checkbox1 = self.checkbox1.get()
    checkbox2 = self.checkbox2.get()
    checkbox3 = self.checkbox3.get()
    date4 = self.date4.get()
    notes = self.entry_notes.get("1.0", "end-1c")

    file_exists = os.path.isfile(self.csv_file)
    with open(self.csv_file, 'a', newline='') as csvfile:
    writer = csv.writer(csvfile)
    if not file_exists:
    writer.writerow([
    'Value1', 'Value2', 'Value3', 'Value4', 'Value5', 'Value6', 'Value7',
    'Value8', 'Value9', 'Value10', 'Value11', 'Value12', 'Value13',
    'Value14', 'Value15', 'Value16', 'Value17', 'Value18',
    'Value19', 'Value20', 'Value21', 'Value22', 'Value23', 'Value24'
    ])
    writer.writerow([
    value1, value2, value3, value4, value5, value6, value7,
    value8, value9, value10, value11, value12, choice,
    date1, date2, date3, date4, checkbox1,
    checkbox2, checkbox3, '', '', notes, ''
    ])

    self.value1.delete(0, tk.END)
    self.value2.delete(0, tk.END)
    self.value3.delete(0, tk.END)
    self.value4.delete(0, tk.END)
    self.value5.delete(0, tk.END)
    self.value6.delete(0, tk.END)
    self.value7.delete(0, tk.END)
    self.value8.delete(0, tk.END)
    self.value9.delete(0, tk.END)
    self.value10.delete(0, tk.END)
    self.value11.delete(0, tk.END)
    self.value12.delete(0, tk.END)
    self.date1.set("")
    self.date2.set("")
    self.date3.set("")
    self.selected_choice.set(self.choice_options[3])
    self.checkbox1.set(0)
    self.checkbox2.set(0)
    self.checkbox3.set("TRUE")
    self.date4.set("")
    self.entry_notes.delete("1.0", "end-1c")

    messagebox.showinfo("Success", "Data submitted successfully!")


    import customtkinter

    from form1 import Form1
    from form2 import Form2


    customtkinter.set_appearance_mode("dark")

    class App(customtkinter.CTk):
    def init(self):
    super().init()
    self.title("Test Project")

    self.geometry('950x500')
    self.form_selector = customtkinter.CTkOptionMenu(self, values=["Form1", "Form2"], state="readonly", command=self.show_selected_form)

    self.form_selector.pack(pady=10)
    self.container = customtkinter.CTkFrame(self)
    self.container.pack(fill=None, expand=True)
    self.forms = {}

    self._init_forms()

    self.form_selector.set("Form1")
    self.show_selected_form(None)

    def _init_forms(self):
    self.forms["Form1"] = Form1(self.container)
    self.forms["Form2"] = Form2(self.container)



    def show_selected_form(self, event):
    selected_name = self.form_selector.get()
    for name, form in self.forms.items():
    form.grid_remove()
    if selected_name:
    self.forms[selected_name].grid()

    if __name__ == "__main__":
    app = App()
    app.mainloop()

    Continue reading...

Compartilhe esta Página