Reputation: 663
In this simple script an item selected in listbox
on Page1
is saved and printed from a Page2
. The value in listbox
is saved in app_data
. The code runs, but no value is recorded in app_data
(the value printed is blank). The following exception occurs:
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
return self.func(*args) File "filepath/file.py", line 35, in <lambda>
button1 = ttk.Button(self,text="Next Page",command=lambda: controller.show_frame(Page2)
or self.controller.app_data["listbox"]
.set(self.listbox.get(self.listbox.curselection())))
AttributeError: 'Page1' object has no attribute 'listbox'
From what I can tell the controller is unable to recognize the listbox. I looked into a possible resolution using super()
as shown in Understanding Python super() with init() methods but have not had success.
Question:
What will enable listbox values to correctly save to app_data
?
button1 = ttk.Button(self,text="Next Page"
,command=lambda: controller.show_frame(Page2)
or self.controller.app_data["listbox"]
.set(self.listbox.get(self.listbox.curselection()))
Full Code:
from tkinter import *
from tkinter import ttk
class MyApp(Tk):
def __init__(self):
Tk.__init__(self)
# App data in controller
self.app_data = {"listbox": StringVar()}
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand = True)
self.frames = {}
for F in (Page1, Page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky = NSEW)
self.show_frame(Page1)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Page1(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
self.controller = controller
listbox = Listbox(self,exportselection=0)
listbox.grid()
for item in [0,1,2,3,4,5]:
listbox.insert(END, item)
button1 = ttk.Button(self,text="Next Page"
,command=lambda: controller.show_frame(Page2)
or self.controller.app_data["listbox"]
.set(self.listbox.get(self.listbox.curselection())))
button1.grid()
class Page2(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
self.controller = controller
ttk.Label(self, text='Next Page').grid(padx=(20,20), pady=(20,20))
button1 = ttk.Button(self, text='Select Page',
command=lambda: controller.show_frame(Page1))
button1.grid()
button2 = ttk.Button(self, text='print value', command=self.print_value)
button2.grid()
def print_value(self):
value = self.controller.app_data["listbox"].get()
print ('The value stored in StartPage some_entry = ' + str(value))
app = MyApp()
app.mainloop()
Upvotes: 0
Views: 2869
Reputation: 16169
Your problem is simple: in button1
definition you use some methods of self.listbox
, but when you defined your listbox, you haven't defined it as an attribute of Page1
: listbox = Listbox(self,exportselection=0)
(no self.
in front of it). That's why you get the error AttributeError: 'Page1' object has no attribute 'listbox'
.
There are two ways to avoid this:
If you need to use the listbox somewhere outside the __init__
method of Page1
, make it an attribute: self.listbox = Listbox(self,exportselection=0)
and replace all the listbox
by self.listbox
.
If you don't need it anywhere else, just change the self.listbox
in listbox
in the button1
definition:
button1 = ttk.Button(self,text="Next Page"
,command=lambda: controller.show_frame(Page2)
or self.controller.app_data["listbox"]
.set(listbox.get(listbox.curselection())))
Upvotes: 1