Posts: 5
Threads: 1
Joined: Jul 2020
Jul-29-2020, 02:06 PM
(This post was last modified: Jul-29-2020, 03:24 PM by Larz60+.)
First of all, I am sorry if I do not comply with the optimal formalities in my first question.
I have programmed a GUI with several windows with Tkinter. Each of these windows has its own entries. When I enter values into the entries and I use the method tkraise() to highlight another window, the values are deleted.
Does anyone know what I can do to keep the values in the entries, even if I change between the windows?
Do I have to save the values first with entryXYZ.get() and set the values in the entries again, if the user switch between the windows(Frames)?
def subframe_AGap(self):
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(self.sub_AGapCanvas, textvariable = self.jobNameA_text)
self.jobNameA_entry.place(x=130, y=120, width = 210)
self.jobNameA_entry.configure({"background": "light green"})
self.A_GapFrame.tkraise()
self.subframe_AGap()
self.A_GapFrame.grid(row=2, column=0, sticky='news') When i put some text in self.jobNameA_text and after that I order to switch to an other Frame B_GapFrame.tkraise() all my values in subframe_AGap() are deleted. Have someone another idea to solve this?
Posts: 6,800
Threads: 20
Joined: Feb 2020
What you describe is not normal behavior, so all you have to do is find the bug in you code.
To get much help you really have to wrap you python code inside python tags.
Quote:[python]
code goes here
[/python]
There is a little python button in the toolbar for doing this.
Without proper formatting it is hard to read your code. Without all the relevant code it is hard to find your error. My guess is you are deleting entries by creating new entries. If there is no reference to an Entry it gets gobbled up by garbage collection. All Python objects have a reference count. The count is essentially how many variables are mapped to the object.
When the count drops to zero the object is deleted and memory is returned to the heap to be reused. Each time you call obj.subframe_AGap(), obj.jobNameA_entry gets pointed at a new Entry. That means it no longer points to the existing entry. If obj.jobNameA_entry was the only variable mapped to the Entry the reference count drops to zero and the Entry object gets deleted.
Though what I say is correct it may not be what is causing your problem. If you could create a small working example that demonstrates the problem I'm sure someone will give you a better answer.
Posts: 5
Threads: 1
Joined: Jul 2020
import tkinter as tk
class Win1:
def __init__(self, master):
self.master = master
self.master.title("Gap Assessment")
self.topFrame = tk.Frame(self.master)
self.topFrame.grid(row=0, column=0, sticky='news', ipady = 5)
self.A_GapFrame = tk.Frame(self.master)
self.B_GapFrame = tk.Frame(self.master)
self.C_GapFrame = tk.Frame(self.master)
self.E_GapFrame = tk.Frame(self.master)
self.F_GapFrame = tk.Frame(self.master)
self.K_GapFrame = tk.Frame(self.master)
# Create a Tkinter variable
self.gapType = tk.StringVar(self.master)
# Dictionary with options
self.choiceGap = ['AFrame','BFrame']
# self.choiceGap = sorted(self.choiceGap)
self.gapType.set('') # set the default option
self.ctngMenu = tk.OptionMenu(self.topFrame, self.gapType, *self.choiceGap, command=self.chioseGap_handle)
self.ctngMenu.grid(row = 1, column =2)
def chioseGap_handle(self, selected):
if selected == 'AFrame':
self.A_GapFrame.tkraise()
self.subframe_AGap()
self.A_GapFrame.grid(row=2, column=0, sticky='news')
if selected == 'BFrame':
self.B_GapFrame.tkraise()
self.subframe_BGap()
self.B_GapFrame.grid(row=2, column=0, sticky='news')
def subframe_AGap(self):
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(self.A_GapFrame, textvariable = self.jobNameA_text)
self.jobNameA_entry.grid(row=1, column=0, sticky='news')
def subframe_BGap(self):
self.jobNameB_text = tk.StringVar()
self.jobNameB_entry = tk.Entry(self.B_GapFrame, textvariable = self.jobNameB_text)
self.jobNameB_entry.grid(row=2, column=0, sticky='news')
root = tk.Tk()
root.geometry("+50+50")
app = Win1(root)
root.mainloop() Thank you for your attention. You can see my problem when you run this code. You will see that, if you enter something in the Entry and then select in the OptionMenue another Frame, you will see that the Entry is empty when you go back to the first Frame.
Posts: 2,168
Threads: 35
Joined: Sep 2016
You are making a new blank entry each time you change frame
Posts: 5
Threads: 1
Joined: Jul 2020
(Jul-29-2020, 04:25 PM)Yoriz Wrote: You are making a new blank entry each time you change frame
Do you know what i have to do, to solve this?
Posts: 2,168
Threads: 35
Joined: Sep 2016
Jul-29-2020, 04:32 PM
(This post was last modified: Jul-29-2020, 04:32 PM by Yoriz.)
Create the entries once only, at the same point of creating the containing frames and not as part of the button event handler
Posts: 6,800
Threads: 20
Joined: Feb 2020
I got it right! Sort of.
Here's a shorter example that demonstrates the problem:
import tkinter as tk
class Win1:
def __init__(self, master):
self.master = master
self.master.title("Gap Assessment")
self.topFrame = tk.Frame(self.master)
self.topFrame.grid(row=0, column=0, sticky='news', ipady = 5)
self.A_GapFrame = tk.Frame(self.master)
# Create a Tkinter variable
self.gapType = tk.StringVar(self.master)
# Dictionary with options
self.choiceGap = ['AFrame']
# self.choiceGap = sorted(self.choiceGap)
self.gapType.set('') # set the default option
self.ctngMenu = tk.OptionMenu(self.topFrame, self.gapType, *self.choiceGap, command=self.chioseGap_handle)
self.ctngMenu.grid(row = 1, column =2)
def chioseGap_handle(self, selected):
self.A_GapFrame.tkraise()
self.subframe_AGap()
self.A_GapFrame.grid(row=2, column=0, sticky='news')
def subframe_AGap(self):
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(self.A_GapFrame, textvariable = self.jobNameA_text)
self.jobNameA_entry.grid(row=1, column=0, sticky='news')
print('A', self.jobNameA_entry)
root = tk.Tk()
root.geometry("+50+50")
app = Win1(root)
root.mainloop() When I run this and make selections from the combo box I see this in the console:
Output: A .!frame2.!entry
A .!frame2.!entry2
A .!frame2.!entry3
A .!frame2.!entry4
Each time I select a frame it creates a new Entry widget. Even if this didn't cause the old Entry widget to be deleted it would still cause previously entered text to disappear behind the new Entry widget that is drawn over the top.
You need to rewrite you code so it only creates one entry widget for each frame.
Posts: 5
Threads: 1
Joined: Jul 2020
(Jul-29-2020, 04:32 PM)Yoriz Wrote: Create the entries once only, at the same point of creating the containing frames and not as part of the button event handler
Thanks. Yes you are right. But the next Problem is, that the widgets from AFrame does not disappear, when i call BFrame. For this reason the BFrame contains widgets which are not supposed to be in there. Do you know what i can do in this case?
Posts: 6,800
Threads: 20
Joined: Feb 2020
(Jul-29-2020, 04:35 PM)robertoCarlos Wrote: (Jul-29-2020, 04:32 PM)Yoriz Wrote: Create the entries once only, at the same point of creating the containing frames and not as part of the button event handler
Thanks. Yes you are right. But the next Problem is, that the widgets from AFrame does not disappear, when i call BFrame. For this reason the BFrame contains widgets which are not supposed to be in there. Do you know what i can do in this case?
Hide them?
Posts: 2,168
Threads: 35
Joined: Sep 2016
Moved self.subframe_AGap() & self.subframe_BGap() from hioseGap_handle to the __init__
import tkinter as tk
class Win1:
def __init__(self, master):
self.master = master
self.master.title("Gap Assessment")
self.topFrame = tk.Frame(self.master)
self.topFrame.grid(row=0, column=0, sticky='news', ipady=5)
self.A_GapFrame = tk.Frame(self.master)
self.B_GapFrame = tk.Frame(self.master)
self.C_GapFrame = tk.Frame(self.master)
self.E_GapFrame = tk.Frame(self.master)
self.F_GapFrame = tk.Frame(self.master)
self.K_GapFrame = tk.Frame(self.master)
self.subframe_AGap()
self.subframe_BGap()
# Create a Tkinter variable
self.gapType = tk.StringVar(self.master)
# Dictionary with options
self.choiceGap = ['AFrame', 'BFrame']
# self.choiceGap = sorted(self.choiceGap)
self.gapType.set('') # set the default option
self.ctngMenu = tk.OptionMenu(
self.topFrame, self.gapType, *self.choiceGap, command=self.chioseGap_handle)
self.ctngMenu.grid(row=1, column=2)
def chioseGap_handle(self, selected):
if selected == 'AFrame':
self.A_GapFrame.tkraise()
self.A_GapFrame.grid(row=2, column=0, sticky='news')
if selected == 'BFrame':
self.B_GapFrame.tkraise()
self.B_GapFrame.grid(row=2, column=0, sticky='news')
def subframe_AGap(self):
self.jobNameA_text = tk.StringVar()
self.jobNameA_entry = tk.Entry(
self.A_GapFrame, textvariable=self.jobNameA_text)
self.jobNameA_entry.grid(row=1, column=0, sticky='news')
def subframe_BGap(self):
self.jobNameB_text = tk.StringVar()
self.jobNameB_entry = tk.Entry(
self.B_GapFrame, textvariable=self.jobNameB_text)
self.jobNameB_entry.grid(row=2, column=0, sticky='news')
root = tk.Tk()
root.geometry("+50+50")
app = Win1(root)
root.mainloop()
|