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.