BioData (2) [Avatar] Offline
#1
Hello, I am creating a GUI that has two Toplevel widgets and a root frame, where I wish for one of the Toplevel widgets to be invisible when I initiate the GUI but which can be made to be seen by clicking a button in the root frame. I can insert the line:

win2.withdraw()

in the start_window code (which builds the entire GUI) which will make the Toplevel widget invisible when the GUI is initialized, but I can't figure out how to re-draw the Toplevel widget once I want it to be visible. I expected the command:

win2.deiconify()

to provide the desired functionality but I get the following error message when I attempt this:

AttributeError: start_window instance has no attribute 'deiconify'

Here is my code, which when mainloop()ed, creates the GUI. I have two separate widget classes that I am using in this code, one is for a ScrolledList widget and the second is for a ScrolledText widget. It is the ScrolledText widget I wish to be invisible when I initiate the GUI and then by clicking a button on the root frame that makes the ScrolledText widget visible.

class start_window(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
#self.pa()
Frame.pack(self)
win1 = Toplevel()
win2 = Toplevel()
Label(self, text = 'Bioasys DataBase', width = 30).pack()
btn = Button(self, text='Make Widget Visible', command=win2.deiconify())
btn.pack(side=TOP)
win1.title('Company Lookup')
win2.title('Company Information')
ScrolledList(win1).pack(side=TOP, fill=BOTH)

#stock_sym = 'acad'

#text1, text2 = create_company_information(stock_sym)


try:
stco_name = ScrolledText(win2, file=sys.argv[1], width= 50, height=15).pack()
except IndexError:
#text1 = 'Company Name - Company Symbol

Company URL

Company Address Line 1
Company Address Line 2
company Address Line 3
Company Address Line 4'
stco_name = ScrolledText(win2, text= text1, width= 50, height=15).pack()

try:
stco_sym = ScrolledText(win2,file=sys.argv[1], width=50, height=15).pack()
except IndexError:
#text2 = 'Company Description'
stco_sym = ScrolledText(win2, text= text2, width=50, height=15).pack()

win2.withdraw() # makes the win2 frame invisible at startup
#win2.pack_forget()
#win2.master.deiconify()

Here is the code for the two different Toplevel widgets, these widget classes both work correctly. I am including this code so that the start_window class can be made to function properly.

class ScrolledList(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.makeWidgets()
def handleList(self, event):
index = self.listbox.curselection()
label = self.listbox.get(index)
self.runCommand(label)
def fetch(self):
print 'Input => "%s"' % self.ent.get()

def makeWidgets(self):
self.ent = Entry(self)
btn = Button(self, text='ENTER', command=self.fetch)
sbar = Scrollbar(self)
list = Listbox(self, relief=SUNKEN)
self.ent.insert(0, 'Type Stock Symbol Here')
self.ent.pack(side=TOP, fill=X)
self.ent.focus()
self.ent.bind('<Return>', (lambda event: self.fetch()))
value = self.ent.get()
btn.pack(side=TOP)
sbar.config(command=list.yview)
list.config(yscrollcommand=sbar.set)
sbar.pack(side=RIGHT, fill=Y)
list.pack(side=LEFT, expand=YES, fill=BOTH)
options = options = map((lambda x: 'Lumberjack-' + str(x)), range(20))
for label in options:
list.insert('end', label)
#list.config(selectmode=SINGLE, setgrid=1)
list.bind('<Double-1>', self.handleList)
self.listbox = list


def runCommand(self, selection):
print 'You selected: ', selection
self.ent.delete(0, END)
self.ent.insert(0, selection)


# a simple text or file viewer component
class ScrolledText(Frame):
def __init__(self, parent=None, text='', file=None, width='', height=''):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH) # make me expandable
self.width = width
self.height = height
self.makewidgets()
self.settext(text, file)
def makewidgets(self):
sbar = Scrollbar(self)
text = Text(self, relief=SUNKEN, width=self.width, height=self.height)
sbar.config(command=text.yview) # xlink sbar and text
text.config(yscrollcommand=sbar.set) # move one moves other
sbar.pack(side=RIGHT, fill=Y) # pack first=clip last
text.pack(side=LEFT, expand=YES, fill=BOTH) # text clipped first
self.text = text
def settext(self, text='', file=None):
if file:
text = open(file, 'r').read()
self.text.delete('1.0', END) # delete current text
self.text.insert('1.0', text) # add at line 1, col 0
self.text.mark_set(INSERT, '1.0') # set insert cursor
self.text.focus() # save user a click
def gettext(self): # returns a string
return self.text.get('1.0', END+'-1c') # first through last


And here is the mainloop() command that intiates the GUI:

start_window().mainloop()

So to summarize I am looking to start my GUI with an invisible Toplevel Win2 widget but by clicking a button on the root frame the Win2 widget can be made visible. If anybody has any ideas on how to accomplish this I would appreciate the help. Sincerely, George
woooee (10) [Avatar] Offline
#2
Re: How do I make a Toplevel widget appear and disapear
This line does not work the way you think it does.
btn = Button(self, text='Make Widget Visible', command=win2.deiconify())
Because of the parens after deiconify the function is called immediately instead of when the button is pressed. Below is a working example with out the unnecessary, for this example, code. One button calls deiconify as a command, and the other calls a function, which calls withdraw, to show how functions work. Note that in both cases there are no parens following the "command=function_name".

Finally, you have to be aware of scope. In the code below, both Toplevels are instance attributes (variables that start with self.), and so can be seen throughout the class. Otherwise, they are local to the function they were created in, or, any other function within the class would not know about them

import sys
if sys.version_info[0] < 3: ## Python 3.x
....import Tkinter as tk
else:
....import tkinter as tk ## Python 2.x

class StartWindow():
....def __init__(self):
........top=tk.Tk()
........fr=tk.Frame(top)
........fr.pack()
........self.win1 = tk.Toplevel()
........self.win2 = tk.Toplevel()
........tk.Label(fr, text = 'Bioasys DataBase', width = 30).pack()
........btn = tk.Button(fr, text='Make Widget Visible',
....................command=self.win2.deiconify)
........btn.pack(side=tk.TOP)
........self.win1.title('Company Lookup')
........self.win2.title('Company Information')
........self.win2.withdraw()

........## put something in the Toplevels so they show
........tk.Button(self.win1, text="withdraw this window", bg="lightblue",
................command=self.win1_withdraw).pack()
........tk.Label(self.win2, text="something in win2", bg="green",
................width=30).pack()

........top.mainloop()

....def win1_withdraw(self):
........self.win1.withdraw()

StartWindow()
BioData (2) [Avatar] Offline
#3
Re: How do I make a Toplevel widget appear and disapear
Hello, Thank you for your reply. It seems my original code needed to redefine each of the win1 and win2 statements, which needed to be modified to self.win1 and self.win2 to allow for these variables to function within the complete start_window class and not just within the __init__ section. The command = self.win2.deiconify() needed to be self.win2.deiconify. Thanks for you help. Sincerely, George
woooee (10) [Avatar] Offline
#4
Re: How do I make a Toplevel widget appear and disapear
This forum is almost abandoned so I would suggest that you ask future questions on Daniweb's Python forum https://www.daniweb.com/software-development/python/114