Python Forum
Thread Rating:
  • 1 Vote(s) - 1 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tkinter problem
#1
Sometimes the internet offers too many choices,
without explicitely stating what the best solution is in what circonstance.
My app involves a user answering multiple choice questions, he has 10 senconds to enter his choice.
When he feels ready, he starts each new question with a "start" button.
This button should disappear when he presses it, only to re-appear when the 10 secs are up. Works fine.
We create the button in a grid like so:
 butOK = Button(root, text=' Start (10s) ', font='ARIAL 14 bold', command=answer, bg='lightgreen')
Now I need to remove it, and i found 3 possibilities:
butOK.grid_remove()
butOK.grid_forget()
butOK.destroy()
10 seconds later i recreate it with the same line as above.
I am getting no errors in either method but the internet warns that:
_remove -> will build up new buttons each time you recreate it, thus penalizing memory usage...?
_forget -> will cause a memory leak ...?
.destroy -> don't know...

Question: what method is the best for creating/ "removing"/creating/ "removing"...etc maybe for 50 questions..;
Maybe there is a 4th method i haven't found yet.
(Of course i could do (state=DISABLED) but that is visually less appealing)
Thx,
Paul
Reply
#2
I've only used .destroy. Haven't heard of the others. Worked fine for me, so I would recommend it.
Reply
#3
Have you looked at using hide/show instead of recreating the button after each time period?
"Often stumped... But never defeated."
Reply
#4
Wrong widget toolkit. No hide/show in tkinter that I can find. Maybe it is the C/C++/C# programmer in me, but I hate the idea of destroying a button just because you want to hide it for a few seconds. This little demo uses pack_forget/pack to hide/show a button. It makes a special frame for the button to make it easier to pack. The demo has a blink feature that I set to 100x a second. Ran for several minutes and saw no change in memory use.
from tkinter import *

class Peekabutton(Frame):

    def __init__(self, root, text=None, textvar=None, command=None, **kwargs):
        super().__init__(root, **kwargs)
        self.root = root
        self.blinking = False
        self.button = Button(self, text=text, textvar=textvar, command=command)
        self.show()

    def show(self):
        self.button.pack(fill=BOTH, expand=1)
        self.visible = True

    def hide(self):
        self.button.pack_forget()
        self.visible = False

    def toggle(self):
        if self.visible:
            self.hide()
        else:
            self.show()

    def blink_event(self):
        if self.blinking:
            self.toggle()
            self.root.after(10, self.blink_event)

    def blink(self):
        self.blinking = not self.blinking
        if self.blinking:
            self.blink_event()
    
root = Tk()
root.title('Hidden Buttons')
root.geometry('300x100')
b2 = Peekabutton(root, text='-a-', height=100, width=100)
b1 = Peekabutton(root, text='Peek', command=b2.blink, height=100, width=100)
b3 = Peekabutton(root, text='Button', command=b2.toggle, height=100, width=100)

b1.pack(side=LEFT, fill=BOTH, expand=1, padx=10, pady=10)
b2.pack(side=LEFT, fill=BOTH, expand=1, padx=10, pady=10)
b3.pack(side=LEFT, fill=BOTH, expand=1, padx=10, pady=10)
Reply
#5
Thanks for the info: grid_forget was my first choice, until
i read something about a "memory leak". Much ado about nothing probably.
.destroy always seemed a bit harsh, frequent grid_remove was memory punishing i read.

For completeness sake, there is a 4th method, one that has probably no incidence whatsoever
on memory, but may drive evangelists mad:
remove text from the widget,
set it to the same bg color as its master and disable it. All this can be done in one config line.
It's not textbook, but it sure works. :-)
Paul
Reply
#6
Another choice is to place two widgets in the same location and lift one over the other (raise in the Z plane). In Qt they have a stacked widget for doing this. It is like a Tk Notebook without the tabs. The visible view is selected programmatically. I was trying to do this with the Peek-a-button demo. Originally I had a button and a frame inside the outer frame. Show raised the button to be visible and Hide raised the frame. I could not figure out how to get both widgets to occupy the same XY space, got frustrated and fell back on forget/pack.
Reply
#7
Should try that, one day Smile

thx,
Paul
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python3 tkinter radiobutton problem Nick_tkinter 14 1,103 Feb-15-2021, 11:01 PM
Last Post: Nick_tkinter
  tkinter python button position problem Nick_tkinter 3 816 Jan-31-2021, 05:15 AM
Last Post: deanhystad
  [Tkinter] ClockIn/Out tkinter problem Maryan 2 610 Oct-12-2020, 03:42 AM
Last Post: joe_momma
  tkinter| listbox.insert problem Maryan 3 818 Sep-29-2020, 05:34 PM
Last Post: Yoriz
  [Tkinter] Tkinter - I have problem after import varaible or function from aGUI to script johnjh 2 943 Apr-17-2020, 08:12 PM
Last Post: johnjh
  [Tkinter] Problem with tkinter when creating .exe file Jan_97 2 2,101 Feb-27-2020, 05:17 PM
Last Post: Jan_97
  [Tkinter] Tkinter problem catlessness 1 826 Jan-15-2020, 05:17 AM
Last Post: Larz60+
  Problem with Submit button Tkinter Reldaing 2 1,372 Jan-05-2020, 01:58 AM
Last Post: balenaucigasa
  tkinter GUI, problem running seperate files fishglue 17 2,338 Oct-15-2019, 02:56 PM
Last Post: Denni
  [python] [Tkinter] Problem bidding combobox with np.array NEL 3 1,330 Aug-04-2019, 11:07 AM
Last Post: Yoriz

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020