Home > database >  How to update tkinter buttons without memory leak?
How to update tkinter buttons without memory leak?

Time:09-16

Code for a minimal example is below.

from tkinter import *
import tkinter as tk

root = Tk()

gender_selected = tk.StringVar()
gender_selected.set('M')

def display_names(gender):
    if gender == 'M': 
        male_state = ACTIVE
        female_state = DISABLED
    else: 
        male_state = DISABLED
        female_state = ACTIVE
    buttn1 = Radiobutton(root, text = 'Bill', value = 'Bill', state = male_state)
    buttn1.place(x=10, y=110)
    buttn2 = Radiobutton(root, text = 'Bob', value = 'Bob', state = male_state)
    buttn2.place(x=10, y=140)
    buttn3 = Radiobutton(root, text = 'Mary', value = 'Mary', state = female_state)
    buttn3.place(x=10, y=170)
    buttn4 = Radiobutton(root, text = 'Sue', value = 'Sue', state = female_state)
    buttn4.place(x=10, y=200)
    if gender == 'M': buttn1.select()
    else: buttn3.select()
    Radiobutton(root, text="Male", variable = gender_selected, value = 'M', 
    command = lambda: display_names(gender_selected.get())).place(x=10, y=30)
    Radiobutton(root, text="Female", variable = gender_selected, value = 'F', 
    command = lambda: display_names(gender_selected.get())).place(x=10, y=60)
  
display_names(gender_selected.get())
 
root.geometry("150x250")
mainloop()

Each time display_names(gender) evaluates, the value of gender_selected affects which of the names are disabled. It seems the memory used in previous use of display_names(gender) is never freed. Is that correct? If I am correct, what is a way to code the above without leaking memory?

CodePudding user response:

The solution is to create the widgets once, and then update them using the configure method. It might look something like the following example.

I took the liberty to reorganize the code a litte in the hope that it makes it a bit more readable. In my experience, grouping geometry management commands together makes it much easier to visualize the layout when looking at the code.

I've also removed the redundant import. You only need to import tkinter once, and the best practice is to not use a wildcard import.

import tkinter as tk

def update_names():
    gender = gender_selected.get()
    if gender == 'M':
        buttn1.select()
        male_state = tk.ACTIVE
        female_state = tk.DISABLED
    else:
        buttn3.select()
        male_state = tk.DISABLED
        female_state = tk.ACTIVE

    buttn1.configure(state=male_state)
    buttn2.configure(state=male_state)
    buttn3.configure(state=female_state)
    buttn4.configure(state=female_state)

root = tk.Tk()
root.geometry("150x250")

gender_selected = tk.StringVar()
gender_selected.set('M')

male_rb = tk.Radiobutton(root, text="Male", variable = gender_selected, value = 'M',
                      command = update_names)
female_rb = tk.Radiobutton(root, text="Female", variable = gender_selected, value = 'F',
                        command = update_names)

buttn1 = tk.Radiobutton(root, text = 'Bill', value = 'Bill')
buttn2 = tk.Radiobutton(root, text = 'Bob', value = 'Bob')
buttn3 = tk.Radiobutton(root, text = 'Mary', value = 'Mary')
buttn4 = tk.Radiobutton(root, text = 'Sue', value = 'Sue')

male_rb.place(x=10, y=30)
female_rb.place(x=10, y=60)
buttn1.place(x=10, y=110)
buttn2.place(x=10, y=140)
buttn3.place(x=10, y=170)
buttn4.place(x=10, y=200)

# set everything to an initial state
update_names()

root.mainloop()
  • Related