I have a problem with some code that I have been working on where I am trying to pass a variable to a 'simpledialog' box. However, when I declare the variable in the __init__ section, the variable cannot be accessed from any other method in the class.
I have created a simplified working example in which I am trying to pass a string to an Entry box so that when the 'simpledialog' is created, the Entry box is already populated. The value can then be changed and the new value is printed to the console.
from tkinter import *
from tkinter.simpledialog import Dialog
class App(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
Button(parent, text="Press Me", command=self.run).grid()
def run(self):
number = "one"
box = PopUpDialog(self, title="Example", number=number)
print(box.values)
class PopUpDialog(Dialog):
def __init__(self, parent, title, number, *args, **kwargs):
Dialog.__init__(self, parent, title)
self.number = number
def body(self, master):
Label(master, text="My Label: ").grid(row=0)
self.e1 = Entry(master)
self.e1.insert(0, self.number) # <- This is the problem line
self.e1.grid(row=0, column=1)
def apply(self):
self.values = (self.e1.get())
return self.values
if __name__ == '__main__':
root = Tk()
app = App(root)
root.mainloop()
When the code is run, and the 'Press Me' button is pressed, I get the following error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
File "C:/Python/scratch.py", line 14, in run
box = PopUpDialog(self, title="Example", number=number)
File "C:/Python/scratch.py", line 20, in __init__
Dialog.__init__(self, parent, title)
File "C:\Python34\lib\tkinter\simpledialog.py", line 148, in __init__
self.initial_focus = self.body(body)
File "C:/Python/scratch.py", line 26, in body
self.e1.insert(0, self.number)
AttributeError: 'PopUpDialog' object has no attribute 'number'
If I comment out the self.e1.insert(0, self.number), the code will otherwise work.
There seems to be little documentation on the 'simpledialog', and I've been using the examples on effbot.org to try and learn more about dialog boxes.
As a side note, if I insert a print(number) line in the __init__ method of the PopUpDialog class, the number will print to the console. Also, if I initialise the self.number variable (eg, self.number = "example") in the body() method, the code works as expected.
I'm sure I'm missing something silly here, but if you could offer any suggestions as to what might be happening, it would be most appreciated.
The problem is in your PopUpDialog class, At the function __init__ you call the line Dialog.__init__(self, parent, title) that calls the body method. The problem is that you initialize the self.number at the next line and that's why self.number is not initialized yet at the body method.
If you switch the lines it will work for you, just like this:
class PopUpDialog(Dialog):
def __init__(self, parent, title, number, *args, **kwargs):
self.number = number
Dialog.__init__(self, parent, title)
EDIT:
As you can see at the __init__ method of the Dialog there is the above line :
self.initial_focus = self.body(body) that calls your body method.
Related
I have a application which I initialize with a login window - once the user and password are verified, it opens the main menu window (Code for that window is below). Previously if the user had no option to logout from the main menu to go back to the login in. But now I have inserted a logout button which SHOULD kill the current window open the former login window.
Problem is that previously I didn't have to retain the state of the login window as I never planned to go back there, but now I do want the option to go back there - so I need to retain the state - therefore I need to uses root.withdraw() as opposed to root.destroy() which seems to the root of my problems (no pun intended)
If I execute the main_menu_window() function directly on my IDE - it works 100%, but if I were to call it from the LoginWindow (the "parent") in my below code I get the error as detailed below:
def main_menu_window(_parent, _user):
def open_user_man(event=None):
user_man_window(main_win)
main_menu_window(_user)
def open_prof_man(event=None):
prof_man_window(main_win, _user)
main_menu_window(_user)
def open_mon_leagues(event=None):
mon_leagues_window(main_win)
main_menu_window(_user)
def back_to_login():
main_win.destroy()
# if _parent is not None:
# _parent.deiconify()
# Hide Login Window
if _parent is not None:
_parent.withdraw()
# Window Setup
main_win = tk.Tk()
main_win.title("11Sixteen Database Management Controller - Main menu")
main_win.geometry("%dx%d+0+0" % (main_win.winfo_screenwidth(), main_win.winfo_screenheight()))
# Object setup
user_man = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\user_man_icon.png',
"LargeGroove", "User Management")
prof_man = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\profile_man_icon.png',
"LargeGroove", "Profile Management")
mon_leas = ImagedButtonWithText(main_win,
'C:\\Users\\rferreira\\GitHub\\11Sixteen\\DatabaseManagentController\\GlobalResources\\Images_Icons\\monitor_leagues_icon.png',
"LargeGroove", "Monitored Leagues")
back_to_mm_btn = ColourSchemedButton(main_win, "PaleGreen", "Logout", width=18)
# Object binding
user_man.btn.config(command=open_user_man)
prof_man.btn.config(command=open_prof_man)
mon_leas.btn.config(command=open_mon_leagues)
back_to_mm_btn.config(command=back_to_login)
# Object placement
back_to_mm_btn.grid(row=0, column=0, columnspan=2, padx=30, pady=20, sticky="nw")
user_man.frame.grid(row=1, column=0, padx=30, pady=20)
prof_man.frame.grid(row=1, column=1, padx=30, pady=20)
mon_leas.frame.grid(row=1, column=2, padx=30, pady=20)
main_win.mainloop()
if __name__ == "__main__":
user = User()
main_menu_window(None, user)
The error I am getting is as follows:
C:\Users\rferreira\AppData\Local\Programs\Python\Python39\python.exe C:/Users/rferreira/GitHub/11Sixteen/DatabaseManagentController/Login/LoginWindow.py
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginWindow.py", line 19, in login_process
validate_login(login_win, email_entry, password_entry, message_label)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginValidation.py", line 54, in validate_login
login_attempt()
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\Login\LoginValidation.py", line 42, in login_attempt
MwW.main_menu_window(parent, user)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\MainMenu\MainMenuWindow.py", line 41, in main_menu_window
user_man = ImagedButtonWithText(main_win,
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\GlobalResources\GuiObjectsFactories.py", line 45, in __init__
self.btn = LargeGroove(self.frame, image=image)
File "C:\Users\rferreira\GitHub\11Sixteen\DatabaseManagentController\GlobalResources\GUIObjectsComponents.py", line 20, in __init__
super().__init__(master=parent, width=130, height=130, relief="groove", **kw)
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2650, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "C:\Users\rferreira\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2572, in __init__
self.tk.call(
_tkinter.TclError: image "pyimage4" doesn't exist
I would love any help or ideas on how to kill this bug. Please let me know if you need more details or further code extracts.
For better context below are further code extracts for the objects called where the errors are triggered
class ImagedButtonWithText(tk.Frame):
def __init__(self, parent, image_path, btn_type, text, **kw):
self.frame = tk.Frame(parent)
# Set up button
image = PhotoImageComp(image_path)
if btn_type == "MicroGroove":
self.btn = MicroGroove(self.frame, image=image)
if btn_type == "LargeGroove":
self.btn = LargeGroove(self.frame, image=image)
self.btn.image = image
self.btn.grid(row=0, column=0)
# Set up text
self.label = tk.Label(self.frame, text=text)
self.label.grid(row=1, column=0)
# --------------------- Buttons ---------------------------
class MicroGroove(tk.Button):
def __init__(self, parent, **kw):
super().__init__(master=parent, width=30, height=20, relief="groove", **kw)
class LargeGroove(tk.Button):
def __init__(self, parent, **kw):
super().__init__(master=parent, width=130, height=130, relief="groove", **kw)
Tkinter never forces you to pass in the master argument. You usually do it like in this:
self.label = tk.Label(self.frame, text=text)
self.frame is the master for the label. Similarly you should pass in the master parameter when creating PhotoImages like this:
image = PhotoImage(image_path, master=parent)
This is only necessary only if you have more than 1 Tk() instance, but I would advise always passing it.
If you don't pass it in, tkinter assumes that the master is the first instance of Tk() that you created. It is a problem because the different instances of Tk() can't talk to each other (most of the time) so the PhotoImage doesn't actually exist according to the second instance of Tk().
I want to subclass Button into OPButtun. OPButton is a regular Button with the capability of writing help messages when the mouse is hovering. OPButton must accept any possible parameter list that thre regular Button constructor would accept, plus two of my own: a message and the Stringvar where to write it in.
This is my code (supposedly runnable)
from tkinter import *
from tkinter import ttk
class OPButton(Button):
""" """
def ___init___(self, parent, string, message, *args, **kwargs):
ttk.Button.__init__(self, parent, *args, **kwargs)
self.bind("<Enter>", command=lambda e: string.set(message))
self.bind("<Leave>", command=lambda e: string.set(""))
if __name__ == '__main__':
root = Tk()
root.str= StringVar()
OPButton(root, root.str, "hovering the button", text="click here").pack()
ttk.Label(root, textvariable=root.str).pack()
root.mainloop()
and the error message:
Traceback (most recent call last):
File "C:\Users\planchoo\oPButton.py", line 19, in <module>
OPButton(root, "Hello World", "Bouton", text="Hello").pack()
TypeError: __init__() takes from 1 to 3 positional arguments but 4 were given
Edit: Below is the corrected code after Bryan's response. Works at perfection (thanks).
from tkinter import *
from tkinter import ttk
class OPButton(Button):
""" """
def __init__(self, parent, string, message, *args, **kwargs):
ttk.Button.__init__(self, parent, *args, **kwargs)
self.bind("<Enter>", lambda e: string.set(message))
self.bind("<Leave>", lambda e: string.set(""))
if __name__ == '__main__':
root = Tk()
root.chaine = StringVar()
OPButton(root, root.chaine, "Bouton", text="Hello").pack()
ttk.Label(root, textvariable=root.chaine).pack()
root.mainloop()
I'm pretty sure the __init__() function you defined was spelled as ___init___().
I have a GUI class with a (button , two entry boxes and a Listbox), I want to insert in Listbox some data from another class. Here is my GUI class...
class GUI(object):
def __init__(self, parent):
frame = Frame(parent.title("CAN Interface"))
frame.pack()
self.lbfirst = Label(frame, text="CAN ID:")
self.lbfirst.grid(row=1,column=0)
self.first = Entry(frame)
self.first.grid(row=2,column=0)
self.lbsecond = Label(frame, text="CAN Data:")
self.lbsecond.grid(row=1,column=2)
self.second = Entry(frame)
self.second.grid(row=2,column=2)
self.number=Button(frame, text="Send", fg="red", command=self.call_comm)
self.number.grid(row=5,column=1)
self.result = Listbox(frame)
self.result.grid(row=9,column=0, columnspan=5, sticky=N+S+E+W)
def call_comm_rxc(self, data1):
print("in call_comm_rxc")
self.data1 = data1
self.result.insert (END, 'CAN ID : '+str(self.data1[0])+'|Length : '+str(self.data1[1])+'|Data : '+str(self.data1[2]))
& this is my other class from which I want to access self.result attribute of GUI class
class Comm(Thread, Format, GUI):
def __init__(self):
Thread.__init__(self) # Call the Thread class's init function
def run(self):
while True:
# here need to add the code which needs to run all the time
print("in true")
self.CAN_Receive()
def CAN_Receive(self):
print("in rxc")
#self.result1 = result1
self.data = Format.UnPack(self,b'\x12\x00\x00\x00\x03\x00\x00\x00\x01\x02\x03\x00\x00\x00\x00\x00')
GUI.call_comm_rxc(self, self.data)
The error which i am facing is "AttributeError: 'Comm' object has no attribute 'result'
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python33\lib\threading.py", line 901, in _bootstrap_inner
self.run()
File "E:\Studies\Ctech\MicroLab Files\example code.py", line 124, in run
self.CAN_Receive()
File "E:\Studies\Ctech\MicroLab Files\example code.py", line 141, in CAN_Receive
GUI.call_comm_rxc(self, self.data)
File "E:\Studies\Ctech\MicroLab Files\example code.py", line 110, in call_comm_rxc
self.result.insert (END, 'CAN ID : '+str(self.data1[0])+'|Length : '+str(self.data1[1])+'|Data : '+str(self.data1[2]))
AttributeError: 'Comm' object has no attribute 'result'
Kindly help me how can i insert in a Listbox from child class (Comm)
The initialization of class GUI is missing in class Comm.
Add GUI.__init__(self, parent) into the Comm.__init__.
There is a main window with menu and the progressbar. A correspondence window with OK button opens upon menu command and the OK button starts the process (here: 3 sec. sleep).
The correspondence window is created via inheritance from a class I have not provided here (If required for answer, please let me know). The methods apply and ok override existing methods in the mother class.
Now my problem: Since the progressbar sits in the main window (class App) and progressbar(start) and progressbar(stop) in the correspondence window I somehow have to pass (start) and (stop) via the mother class tkSimpleDialog.Dialog to class App. So I thought I also override the __init__(self..) method, provide self. to progressbar.
How can I make this work?
import Tkinter, ttk, tkFileDialog, tkSimpleDialog, time, threading
class App:
def __init__(self, master, progressbar):
self.progress_line(master)
def progress_line (self, master):
self.progressbar = ttk.Progressbar(master, mode='indeterminate')
self.progressbar.place(anchor = 'ne', height = "20", width = "150", x = "175", y = "30")
class AppMenu(object):
def __init__(self, master, progressbar):
self.master = master
self.menu_bar()
def menu_bar(self):
menu_bar = Tkinter.Menu(self.master)
self.menu_bar = Tkinter.Menu(self.master)
self.master.config(menu=self.menu_bar)
self.create_menu = Tkinter.Menu(self.menu_bar, tearoff = False)
self.create_menu.add_command(label = "do", command = self.do)
self.menu_bar.add_cascade(label = "now", menu = self.create_menu)
def do(self):
do1 = Dialog(self.master, progressbar)
class Dialog(tkSimpleDialog.Dialog):
def __init__(self, parent, progressbar):
tkSimpleDialog.Dialog.__init__(self, parent, progressbar)
self.transient(parent)
self.parent = parent
self.result = None
self.progressbar = progressbar
body = Frame(self)
self.initial_focus = self.body(body)
body.pack(padx=5, pady=5)
self.buttonbox()
self.grab_set()
if not self.initial_focus:
self.initial_focus = self
self.protocol("WM_DELETE_WINDOW", self.cancel)
self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50))
self.initial_focus.focus_set()
self.wait_window(self)
def ok(self, event=None):
self.withdraw()
self.start_foo_thread()
self.cancel()
def apply(self):
time.sleep(5)
def start_foo_thread(self):
global foo_thread
self.foo_thread = threading.Thread(target=self.apply)
self.foo_thread.daemon = True
self.progressbar.start()
self.foo_thread.start()
master.after(20, check_foo_thread)
def check_foo_thread(self):
if self.foo_thread.is_alive():
root.after(20, self.check_foo_thread)
else:
self.progressbar.stop()
master = Tkinter.Tk()
progressbar = None
app = App(master, progressbar)
appmenu = AppMenu(master, progressbar)
master.mainloop()
error messages:
first after clicking ok:
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
File "ask-progressbar.py", line 57, in ok
self.start_foo_thread()
File "ask-progressbar.py", line 66, in start_foo_thread
self.progressbar.start()
AttributeError: Dialog2 instance has no attribute 'progressbar'
second: after closing app
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
File "ask-progressbar.py", line 26, in do
do1 = Dialog2(self.master, progressbar)
File "ask-progressbar.py", line 33, in __init__
self.transient(parent)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1652, in wm_transient
TclError: can't invoke "wm" command: application has been destroyed
Below is a working version of your code. There were a number of issues I had to fix because you didn't change a number of things in the code from my answer to your other question about progressbars.
The answer to your main question here is basically that you have to pass the instance around and remember it when necessary in the various class instances involved so that their methods will have it available through theself argument when they need it. Also, the way you were trying to derive and override the tkSimpleDialog.Dialog base class methods was both over-complicated and incorrect as well.
Usually the best (and simplest) thing to do is just supply your own validate() and apply() methods since that's how it was designed to work. If you also need your own __init__() constructor, it's important to only pass parameters to the base class' method that it understands from within the one in the subclass. If you need more functionality, it can usually be provided via additional derived-class-only methods, that only it or other classes you've also created know about.
Anyway, here's what I ended-up with:
import Tkinter, ttk, tkFileDialog, tkSimpleDialog, time, threading
class App:
def __init__(self, master):
self.progress_line(master)
def progress_line(self, master):
# the value of "maximum" determines how fast progressbar moves
self._progressbar = ttk.Progressbar(master, mode='indeterminate',
maximum=4) # speed of progressbar
self._progressbar.place(anchor='ne', height="20", width="150",
x="175", y="30")
#property
def progressbar(self):
return self._progressbar # return value of private member
class AppMenu(object):
def __init__(self, master, progressbar):
self.master = master
self.menu_bar()
self.progressbar = progressbar
def menu_bar(self):
self.menu_bar = Tkinter.Menu(self.master)
self.master.config(menu=self.menu_bar)
self.create_menu = Tkinter.Menu(self.menu_bar, tearoff=False)
self.create_menu.add_command(label="do", command=self.do)
self.menu_bar.add_cascade(label="now", menu=self.create_menu)
def do(self):
Dialog(self.master, self.progressbar) # display the dialog box
class Dialog(tkSimpleDialog.Dialog):
def __init__(self, parent, progressbar):
self.progressbar = progressbar
tkSimpleDialog.Dialog.__init__(self, parent, title="Do foo?")
def apply(self):
self.start_foo_thread()
# added dialog methods...
def start_foo_thread(self):
self.foo_thread = threading.Thread(target=self.foo)
self.foo_thread.daemon = True
self.progressbar.start()
self.foo_thread.start()
master.after(20, self.check_foo_thread)
def check_foo_thread(self):
if self.foo_thread.is_alive():
master.after(20, self.check_foo_thread)
else:
self.progressbar.stop()
def foo(self): # some time-consuming function...
time.sleep(3)
master = Tkinter.Tk()
master.title("Foo runner")
app = App(master)
appmenu = AppMenu(master, app.progressbar)
master.mainloop()
Hope this helps.
Here's another, simpler, solution that doesn't require the use of threading -- so could be easier to use/adapt in your case. It calls the progressbar widget's update_idletasks() method multiple times during the time-consuming foo() function. Again, it illustrates how to pass the progressbar around to the various parts of the code that need it.
import Tkinter, ttk, tkFileDialog, tkSimpleDialog, time
class App:
def __init__(self, master):
self.progress_line(master)
def progress_line(self, master):
self._progressbar = ttk.Progressbar(master, mode='indeterminate')
self._progressbar.place(anchor='ne', height="20", width="150",
x="175", y="30")
#property
def progressbar(self):
return self._progressbar # return value of private member
class AppMenu(object):
def __init__(self, master, progressbar):
self.master = master
self.menu_bar()
self.progressbar = progressbar
def menu_bar(self):
self.menu_bar = Tkinter.Menu(self.master)
self.master.config(menu=self.menu_bar)
self.create_menu = Tkinter.Menu(self.menu_bar, tearoff=False)
self.create_menu.add_command(label="do foo", command=self.do_foo)
self.menu_bar.add_cascade(label="now", menu=self.create_menu)
def do_foo(self):
confirm = ConfirmationDialog(self.master, title="Do foo?")
self.master.update() # needed to completely remove conf dialog
if confirm.choice:
foo(self.progressbar)
class ConfirmationDialog(tkSimpleDialog.Dialog):
def __init__(self, parent, title=None):
self.choice = False
tkSimpleDialog.Dialog.__init__(self, parent, title=title)
def apply(self):
self.choice = True
def foo(progressbar):
progressbar.start()
for _ in range(50):
time.sleep(.1) # simulate some work
progressbar.step(10)
progressbar.update_idletasks()
progressbar.stop()
master = Tkinter.Tk()
master.title("Foo runner")
app = App(master)
appmenu = AppMenu(master, app.progressbar)
master.mainloop()
I'm new to python. I'm trying to open a dialog box to get a value from within a widget that does a list of other staff allready.
But getting errors and can't figure out what to do.
Here's my code:
import Tkinter,Tkconstants,tkFileDialog
from Tkinter import *
import csv
import numpy
import math
import numpy.random as nrnd
import matplotlib.pyplot as plt
import shutil
import tkMessageBox
global filesavepath
class App:
def __init__(self,master):
self.mymaster=master
frame=Frame(master)
frame.pack()
self.importbutton=Button(frame,text='Import Data',command=self.importdata)
self.importbutton.pack()
self.executebutton=Button(frame,text='Execute',command=self.popup)
self.executebutton.pack()
self.distribution_rep=Button(frame,text='Repeat Purchase Score Distribution',command=self.distrepbutton)
self.distribution_rep.pack()
self.distribution_churn=Button(frame,text='Churn Probability Distribution',command=self.distchurnbutton)
self.distribution_churn.pack()
self.exitbutton=Button(frame,text='Exit',command=self.exitapp)
self.exitbutton.pack()
self.file_opt=options={}
options['defaultextension']=''
options['filetypes']=[('allfiles','.*'),('textfiles','.txt')]
options['initialdir']='C:\\'
options['initialfile']='myfile.txt'
options['parent']=root
options['title']='Thisisatitle'
def importdata(self):
filename=tkFileDialog.askopenfilename(**self.file_opt)
filesavepath="C:/input_full.csv"
shutil.copy2(filename,filesavepath)
if filename:
return open(filename,'r')
def popup(self):
top = self.top = Tkinter.Toplevel(self)
myLabel = Tkinter.Label(top, text='Enter your username below')
myLabel.pack()
self.myEntryBox = Tkinter.Entry(top)
self.myEntryBox.pack()
mySubmitButton = Tkinter.Button(top, text='Done', command=self.execbutton)
mySubmitButton.pack()
def execbutton(self):
if self.myEntryBox.get() != "":
self.timevalue = self.myEntryBox.get()
self.top.destroy()
execfile("Repeat Purchase Algo in python v6")
tkMessageBox.showinfo("Job Done", "Probability Computation completed")
def send(self):
global timevalue
timevalue=self.myEntryBox.get()
self.top.destroy()
def distrepbutton(self):
plt.hist(prob,bins=10,normed=TRUE)
plt.xlabel('Probability')
plt.title('Histogram of Repeat Purchase Probability')
plt.show()
def distchurnbutton(self):
plt.hist(churn_prob,bins=10,normed=TRUE)
plt.ylabel('Probability')
plt.title('Histogram of Churn Probability')
plt.show()
def exitapp(self):
self.mymaster.destroy()
root=Tk()
root.title('Repeat Puchase Widget')
app=App(root)
root.mainloop()
So as may be apparent to you, I'm importing dataset with an Import button, executing some analysis in another code through a button called Execute, and then showing some graphs.
What I wanted was to open a pop up kind of window on click of "Execute" button that will input a value. But I'm getting the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:/Python27/widget_repeat_purchase_v4", line 42, in popup
top = self.top = Tkinter.Toplevel(self)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2017, in __init__
BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1965, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1943, in _setup
self.tk = master.tk
AttributeError: App instance has no attribute 'tk'
I've no idea what to do. Please help.
When you create the toplevel widget, you are passing self as the first argument. Tkinter requires that this be a parent widget. However, in your code self does not represent a widget.
In your specific case you want to pass in self.mymaster rather than self:
top = self.top = Tkinter.Toplevel(self.mymaster)
Use Tkinter.Toplevel() instead of Tkinter.Toplevel(self)