Python Forum
Tkinter problem - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: Tkinter problem (/thread-27131.html)



Tkinter problem - DPaul - May-27-2020

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


RE: Tkinter problem - Knight18 - May-27-2020

I've only used .destroy. Haven't heard of the others. Worked fine for me, so I would recommend it.


RE: Tkinter problem - DT2000 - May-27-2020

Have you looked at using hide/show instead of recreating the button after each time period?


RE: Tkinter problem - deanhystad - May-28-2020

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)



RE: Tkinter problem - DPaul - May-28-2020

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


RE: Tkinter problem - deanhystad - May-28-2020

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.


RE: Tkinter problem - DPaul - May-28-2020

Should try that, one day Smile

thx,
Paul