Getting the choice of optionmenu right after selection Python - python-2.7

I was wondering if there is any way for me to see what the User has selected among the list displaying, let's say: ["Apple","Orange","Grapes"] right after they select either one of them?
Like when user clicks the optionbox, and clicks Apple, Tkinter will return something
then if he switches his selection to, let's say, Orange, then that will also return something on the spot.
Thanks!
How to put parameter correctly?
from Tkinter import *
def option_changed(a):
print "the user chose the value {}".format(variable.get())
print a
master = Tk()
a = "Foo"
variable = StringVar(master)
variable.set("Apple") # default value
variable.trace("w", option_changed(a))
w = OptionMenu(master, variable, "Apple", "Orange", "Grapes")
w.pack()
mainloop()

Trace the StringVar.
from Tkinter import *
def option_changed(*args):
print "the user chose the value {}".format(variable.get())
print a
master = Tk()
a = "Foo"
variable = StringVar(master)
variable.set("Apple") # default value
variable.trace("w", option_changed)
w = OptionMenu(master, variable, "Apple", "Orange", "Grapes")
w.pack()
mainloop()
Here, option_changed will be called whenever the user chooses an option from the option menu.
You can wrap the trace argument in a lambda to specify your own parameters.
def option_changed(foo, bar, baz):
#do stuff
#...
variable.trace("w", lambda *args: option_changed(qux, 23, "hello"))

When I come across widgets with annoying interfaces - such as OptionMenu, I generally will write a class around it to abstract away the annoying attributes. In this case, I really dislike the verbosity of using the StringVar every time I want to create a dropdown, so I simply created a DropDown class which includes the StringVar within the class (written in Python 3.5, but translates easily to all):
class DropDown(tk.OptionMenu):
"""
Classic drop down entry
Example use:
# create the dropdown and grid
dd = DropDown(root, ['one', 'two', 'three'])
dd.grid()
# define a callback function that retrieves the currently selected option
def callback():
print(dd.get())
# add the callback function to the dropdown
dd.add_callback(callback)
"""
def __init__(self, parent, options: list, initial_value: str=None):
"""
Constructor for drop down entry
:param parent: the tk parent frame
:param options: a list containing the drop down options
:param initial_value: the initial value of the dropdown
"""
self.var = tk.StringVar(parent)
self.var.set(initial_value if initial_value else options[0])
self.option_menu = tk.OptionMenu.__init__(self, parent, self.var, *options)
self.callback = None
def add_callback(self, callback: callable):
"""
Add a callback on change
:param callback: callable function
:return:
"""
def internal_callback(*args):
callback()
self.var.trace("w", internal_callback)
def get(self):
"""
Retrieve the value of the dropdown
:return:
"""
return self.var.get()
def set(self, value: str):
"""
Set the value of the dropdown
:param value: a string representing the
:return:
"""
self.var.set(value)
Example usage:
# create the dropdown and grid, this is the ONLY required code
dd = DropDown(root, ['one', 'two', 'three'])
dd.grid()
# optionally, define a callback function that retrieves the currently selected option then add that callback to the dropdown
def callback():
print(dd.get())
dd.add_callback(callback)
Edited to add: Not long after creating this post, I got annoyed with a few other attributes of tk and ended up creating a package called tk_tools to make dropdowns and checkbuttons easier along with addressing other annoyances.

Related

How To Get the row and column number for a widget placed in grid in tkinter python?

I have placed multiple Combobox in the grid as shown below.
These comboboxes are stored in array with corresponding row, column for eg as shown below.
self.c_arr[row,column] = ttk.Combobox(what_ev,
textvariable=self.c_it_val[row,column],
values=list(self.c_list[row,column].keys()))
self.c_arr[row,column].bind("<<ComboboxSelected>>", lambda
x:self.c_capture(what_ev, <Want to pass row, column information as well>))
Whenever the function bound to the combobox is called/triggered, I wanted to pass the respective row, column number to the called function along with other variables.
How to get/retrieve the respective widgets row,column number/location details placed on the grid?
UPDATE: Adding with an Example code below.
The below code create a 3x3 COmbobox and binded with a function to get called when any of the respective combobox is selected. When gets selected I wanted to get the value selected in that box and print it.
Example Code:
import Tkinter
from Tkinter import *
from Tkinter import Tk, StringVar
import ttk
import tkFont
class Application:
def __init__(self, parent):
self.parent = parent
self.sco1 = None
self.c_int_val = StringVar()
self.box = {}
self.box_value = {}
self.box_int_list = {}
self.combo()
def combo(self):
for row in range (3):
for column in range(3):
self.box_int_list[row,column] = {key: None for key in range(1,10)}
self.box_value[row,column] = StringVar()
self.box_value[row,column].set("0")
self.box[row,column] = ttk.Combobox(self.parent, textvariable=self.box_value[row,column], values = list(self.box_int_list[row,column].keys()), state='readonly', width=39)
self.box[row,column].bind("<<ComboboxSelected>>", lambda x:self.print_selected_value("Eurekaa", len(self.box_int_list[row,column])))
self.box[row,column].grid(row=row, column=column)
def print_selected_value(self, what_name, list_len, *args):
print "Value selected is: %s"%(self.box[row,column].get())
print what_name
print list_len
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
But since I wasnt able to get the row,column info, was unable to get the value from the selected combobox. How can that be done ?
If you pass the event to your callback, you can use grid_info on the widget associated with the event.
def callback(event, row, column):
print(row, column)
cb.bind("<<ComboboxSelected>>", callback)
If you want to pass the information, there's nothing preventing you from doing that using lambda or functools.partial:
c.bind("<<ComboboxSelected>>",
lambda event, row=row, column=column: callback(event, row, column))

how to get ticking timer with dynamic label?

What im trying to do is that whenever cursor is on label it must show the time elapsed since when it is created it does well by subtracting (def on_enter(i)) the value but i want it to be ticking while cursor is still on label.
I tried using after function as newbie i do not understand it well to use on dynamic labels.
any help will be appreciated thx
code:
from Tkinter import *
import datetime
date = datetime.datetime
now = date.now()
master=Tk()
list_label=[]
k=[]
time_var=[]
result=[]
names=[]
def delete(i):
k[i]=max(k)+1
time_var[i]='<deleted>'
list_label[i].pack_forget()
def create():#new func
i=k.index(max(k))
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack_forget()
list_label[i].pack(anchor='w')
time_var[i]=time_now()
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack(anchor='w')
k[i]=0
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
def on_leave(i):
list_label[i].configure(text=names[i])
def time_now():
now = date.now()
return date(now.year,now.month,now.day,now.hour,now.minute,now.second)
############################
for i in range(11):
lb=Label(text=str(i),anchor=W)
list_label.append(lb)
lb.pack(anchor='w')
lb.bind("<Button-3>",lambda event,i=i:delete(i))
k.append(0)
names.append(str(i))
lb.bind("<Enter>",lambda event,i=i: on_enter(i))
lb.bind("<Leave>",lambda event,i=i: on_leave(i))
time_var.append(time_now())
master.bind("<Control-Key-z>",lambda event: create())
mainloop()
You would use after like this:
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
list_label[i].timer = list_label[i].after(1000, on_enter, i)
def on_leave(i):
list_label[i].configure(text=names[i])
list_label[i].after_cancel(list_label[i].timer)
However, your approach here is all wrong. You currently have some functions and a list of data. What you should do is make a single object that contains the functions and data together and make a list of those. That way you can write your code for a single Label and just duplicate that. It makes your code a lot simpler partly because you no longer need to keep track of "i". Like this:
import Tkinter as tk
from datetime import datetime
def time_now():
now = datetime.now()
return datetime(now.year,now.month,now.day,now.hour,now.minute,now.second)
class Kiran(tk.Label):
"""A new type of Label that shows the time since creation when the mouse hovers"""
hidden = []
def __init__(self, master=None, **kwargs):
tk.Label.__init__(self, master, **kwargs)
self.name = self['text']
self.time_var = time_now()
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
self.bind("<Button-3>", self.hide)
def on_enter(self, event=None):
self.configure(text=time_now()-self.time_var)
self.timer = self.after(1000, self.on_enter)
def on_leave(self, event=None):
self.after_cancel(self.timer) # cancel the timer
self.configure(text=self.name)
def hide(self, event=None):
self.pack_forget()
self.hidden.append(self) # add this instance to the list of hidden instances
def show(self):
self.time_var = time_now() # reset time
self.pack(anchor='w')
def undo(event=None):
'''if there's any hidden Labels, show one'''
if Kiran.hidden:
Kiran.hidden.pop().show()
def main():
root = tk.Tk()
root.geometry('200x200')
for i in range(11):
lb=Kiran(text=i)
lb.pack(anchor='w')
root.bind("<Control-Key-z>",undo)
root.mainloop()
if __name__ == '__main__':
main()
More notes:
Don't use lambda unless you are forced to; it's known to cause bugs.
Don't use wildcard imports (from module import *), they cause bugs and are against PEP8.
Put everything in functions.
Use long, descriptive names. Single letter names just waste time. Think of names as tiny comments.
Add a lot more comments to your code so that other people don't have to guess what the code is supposed to do.
Try a more beginner oriented forum for questions like this, like learnpython.reddit.com

How to manage absolute coordinate window in gtk3 python

I translated TreeView gtk2 tooltip in Gtk3
It's almost running but I have problem to manage coordinate of tooltip window.
I Would like the tooltip window locate near the mouse et follow it near. Instead of my project where the tooltip window is located in the corner of screen
my code is
#!/usr/bin/env python
# coding: utf-8
'''
warning data not update !!!!!!!!!!!!!
TreeViewTooltips.py
Provides TreeViewTooltips, a class which presents tooltips for cells,
columns and rows in a Gtk.TreeView.
------------------------------------------------------------
This file includes a demo. Just execute the file:
python TreeViewTooltips.py
------------------------------------------------------------
To use, first subclass TreeViewTooltips and implement the get_tooltip()
method; see below. Then add any number of Gtk.TreeVew widgets to a
TreeViewTooltips instance by calling the add_view() method. Overview
of the steps:
# 1. subclass TreeViewTooltips
class MyTooltips(TreeViewTooltips):
# 2. overriding get_tooltip()
def get_tooltip(...):
...
# 3. create an instance
mytips = MyTooltips()
# 4. Build up your Gtk.TreeView.
myview = Gtk.TreeView()
...# create columns, set the model, etc.
# 5. Add the view to the tooltips
mytips.add_view(myview)
How it works: the add_view() method connects the TreeView to the
"motion-notify" event with the callback set to a private method.
Whenever the mouse moves across the TreeView the callback will call
get_tooltip() with the following arguments:
get_tooltip(view, column, path)
where,
view: the Gtk.TreeView instance.
column: the Gtk.TreeViewColumn instance that the mouse is
currently over.
path: the path to the row that the mouse is currently over.
Based on whether or not column and path are checked for specific
values, get_tooltip can return tooltips for a cell, column, row or the
whole view:
Column Checked Path Checked Tooltip For...
Y Y cell
Y N column
N Y row
N N view
get_tooltip() should return None if no tooltip should be displayed.
Otherwise the return value will be coerced to a string (with the str()
builtin) and stripped; if non-empty, the result will be displayed as
the tooltip. By default, the tooltip popup window will be displayed
centered and just below the pointer and will remain shown until the
pointer leaves the cell (or column, or row, or view, depending on how
get_tooltip() is implemented).
'''
from gi.repository import Gtk
class TreeViewTooltips_gtk3:
"""tooltip atttach to Treeview in Gtk3
this window is moving to follow row of Treeview"""
def __init__(self):
self.win = Gtk.Window()
self.win.set_decorated(False)
self.win.set_default_size(-1, -1)
self.label = Gtk.Label()
self.win.add(self.label)
# by default, the tooltip is enabled
self.__enabled = True
def __show(self, tooltip, x, y):
"""in order to move the tooltip near row of Treeview"""
self.label.set_markup(tooltip)
w,h = self.win.get_preferred_width()
# move the window
self.win.move(*self.location(x,y,w,h))
# show it
self.win.show_all()
return self.win
def __leave_handler(self, view, event):
"""when the pointer leaves the view, hide the tooltip"""
self.win.hide()
def enable(self):
'Enable the tooltip'
self.__enabled = True
def disable(self):
'Disable the tooltip'
self.__enabled = False
def location(self, x, y, w, h):
'''Given the x,y coordinates of the pointer and the width and
height (w,h) demensions of the tooltip window, return the x, y
coordinates of the tooltip window.
The default location is to center the window on the pointer
and 4 pixels below it.
# en clair c'est un décalage de position de la fenetre qui s'ouvre qui donne l'info
'''
return x - w/2, y + 4
def tooltip_callback(self,treeview, x, y, keyboard_mode, tooltip):
""" in order to collect miscellaneous elemnt to build data with row of treeview"""
"""3eme règle implementer ça pour afficher un tooltip customisé en fonction des data du tree view"""
x, y = treeview.convert_widget_to_bin_window_coords(x, y)
if not self.__enabled :
"""if you don't want tooltip display just return False !!!!"""
return False
try:
path, column, cell_x, cell_y = treeview.get_path_at_pos(x, y)
iter = model.get_iter(path)
#print 'tooltip=',self.get_tooltip(column, self.cust_col,path)
treeview.set_tooltip_window(self.__show(self.get_tooltip(column, self.cust_col,path),x,y))
# necessary to return True in order to display window tooltip
print "path is valid :-)"
return True
except:
# to prevent case when path it's not valid
print "perhaps path it's not valid ????"
# not possible to display something
return False
def add_view(self, view):
"""add a Gtk.TreeView to the tooltip
check if view is instance of Gtk.TreeView
and build connector and tooltip enable"""
assert isinstance(view, Gtk.TreeView), \
('This handler should only be connected to '
'instances of Gtk.TreeView')
# first condition in gtk3
# set True the property "has-tooltip"
view.set_property("has-tooltip", True)
# second condition in gtk3
view.connect('query-tooltip',self.tooltip_callback)
# hide tooltip when mouse out of widget
view.connect("leave-notify-event", self.__leave_handler)
def get_tooltip(self, view, column, path):
"""in order to secure customized implementation in your projet"""
'See the module doc string for a description of this method'
raise NotImplemented, 'Subclass must implement get_tooltip()'
if __name__ == '__main__':
class DemoTips_Gtk3(TreeViewTooltips_gtk3):
"""demo play how to """
def __init__(self, customer_column):
"""
init class
customer_column is an instance of Gtk.TreeViewColumn and
is being used in the Gtk.TreeView to show customer names."""
self.cust_col = customer_column
# call base class init
TreeViewTooltips_gtk3.__init__(self)
def get_tooltip(self, column,cust_col,path):
"""By checking both column and path we have a cell-based tooltip"""
model = view.get_model()
customer = model[path][2]
if column is cust_col:
"""here there is lot of information on row"""
return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname,
customer.lname,
customer.notes)
else:
"""here basic data only !!!!"""
return ('<big><u>Generic Column Tooltip</u></big>\n'
'Unless otherwise noted, all\n phone number is %s ') % customer.phone
# Here's our customer
class Customer:
def __init__(self, fname, lname, phone, notes):
self.fname = fname
self.lname = lname
self.phone = phone
self.notes = notes
# create a bunch of customers
customers = []
for fname, lname, phone, notes in [
('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'),
('Jane', 'Doe', '555-2323',
'Wonders what the hell\nMorris dancing is.'),
('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'),
('Betty', 'Boop', '555-3434', 'Dreams in b&w.'),
('Red Sox', 'Fan', '555-4545',
"Still livin' 2004!\nEspecially after 2006.")]:
customers.append(Customer(fname, lname, phone, notes))
# Build our model and view
model = Gtk.ListStore(str, str, object)
for c in customers:
model.append(['%s %s' % (c.fname, c.lname), c.phone, c])
view = Gtk.TreeView(model)
# two columns, name and phone
cell = Gtk.CellRendererText()
cell.set_property('xpad', 20)
namecol = Gtk.TreeViewColumn('Customer Name', cell, text=0)
namecol.set_min_width(200)
view.append_column(namecol)
cell = Gtk.CellRendererText()
phonecol = Gtk.TreeViewColumn('Phone', cell, text=1)
view.append_column(phonecol)
# finally, connect the tooltip, specifying the name column as the
# column we want the tooltip to popup over.
tips = DemoTips_Gtk3(namecol)
tips.add_view(view)
# We're going to demonstrate enable/disable. First we need a
# callback function to connect to the toggled signal.
def toggle(button):
if button.get_active():
tips.disable()
else:
tips.enable()
# create a checkbutton and connect our handler
check = Gtk.CheckButton('Check to disable view tooltips')
check.connect('toggled', toggle)
check.set_tooltip_markup('This is a standard Gtk tooltip.\n'
'Compare me to the tooltips above.')
# create a VBox to pack the view and checkbutton
vbox = Gtk.VBox()
vbox.pack_start(view,False,False,2)
vbox.pack_start(check,False,False,2)
vbox.show_all()
# pack the vbox into a simple dialog and run it
dialog = Gtk.Dialog('TreeViewTooltips Demo')
close = dialog.add_button(Gtk.STOCK_CLOSE,Gtk.ResponseType.NONE)
# add a tooltip for the close button
close.set_tooltip_markup('Click to end the demo.')
dialog.set_default_size(400,400)
dialog.vbox.pack_start(vbox,False,False,2)
dialog.run()
Who could give me elemnt in order to put tooltip with relative coordinate with TreeView ?
thank by advance
I'am sorry for my bad english
You are working with local coordinates, so you need to refer to the dialog position to get the root coordinates. Another issue with your script is that the main window is a dialog, therefore in the foreground, the tooltips appear below it (I have fixed that but then deleted the code (oops). It works, just change your dialog for a normal window). As a general note, it is good for all widget to know its parent to refer to it when the root coordinates are required.
Please see modified (but not cleaned up) code below:
#!/usr/bin/env python
# coding: utf-8
from gi.repository import Gtk
class TreeViewTooltips_gtk3:
"""tooltip atttach to Treeview in Gtk3
this window is moving to follow row of Treeview"""
def __init__(self):
self.win = Gtk.Window()
self.win.set_decorated(False)
self.win.set_default_size(-1, -1)
self.label = Gtk.Label()
self.win.add(self.label)
# by default, the tooltip is enabled
self.__enabled = True
def __show(self, tooltip, x, y):
"""in order to move the tooltip near row of Treeview"""
self.label.set_markup(tooltip)
w,h = self.win.get_preferred_width()
# move the window
self.win.move(*self.location(x,y,w,h))
# show it
self.win.show_all()
return self.win
def __leave_handler(self, view, event):
"""when the pointer leaves the view, hide the tooltip"""
self.win.hide()
def enable(self):
'Enable the tooltip'
self.__enabled = True
def disable(self):
'Disable the tooltip'
self.__enabled = False
def location(self, x, y, w, h):
'''Given the x,y coordinates of the pointer and the width and
height (w,h) demensions of the tooltip window, return the x, y
coordinates of the tooltip window.
The default location is to center the window on the pointer
and 4 pixels below it.
# en clair c'est un décalage de position de la fenetre qui s'ouvre qui donne l'info
'''
return x - w/2, y + 4
def tooltip_callback(self,treeview, x, y, keyboard_mode, tooltip):
""" in order to collect miscellaneous elemnt to build data with row of treeview"""
"""3eme règle implementer ça pour afficher un tooltip customisé en fonction des data du tree view"""
root_x, root_y = self.dialog.get_position() #get the root coordinates
x, y = treeview.convert_widget_to_bin_window_coords(x, y)
if not self.__enabled :
"""if you don't want tooltip display just return False !!!!"""
return False
try:
path, column, cell_x, cell_y = treeview.get_path_at_pos(x, y)
iter = model.get_iter(path)
#print 'tooltip=',self.get_tooltip(column, self.cust_col,path)
#add the root coordinates to local coordinates
treeview.set_tooltip_window(self.__show(self.get_tooltip(column, self.cust_col,path),root_x+x,root_y+y))
# necessary to return True in order to display window tooltip
print("path is valid :-)")
return True
except:
# to prevent case when path it's not valid
print("perhaps path it's not valid ????")
# not possible to display something
return False
def add_view(self, view):
"""add a Gtk.TreeView to the tooltip
check if view is instance of Gtk.TreeView
and build connector and tooltip enable"""
assert isinstance(view, Gtk.TreeView), \
('This handler should only be connected to '
'instances of Gtk.TreeView')
# first condition in gtk3
# set True the property "has-tooltip"
view.set_property("has-tooltip", True)
# second condition in gtk3
view.connect('query-tooltip',self.tooltip_callback)
# hide tooltip when mouse out of widget
view.connect("leave-notify-event", self.__leave_handler)
def get_tooltip(self, view, column, path):
"""in order to secure customized implementation in your projet"""
'See the module doc string for a description of this method'
raise NotImplemented('Subclass must implement get_tooltip()')
if __name__ == '__main__':
class DemoTips_Gtk3(TreeViewTooltips_gtk3):
"""demo play how to """
def __init__(self, customer_column):
"""
init class
customer_column is an instance of Gtk.TreeViewColumn and
is being used in the Gtk.TreeView to show customer names."""
self.cust_col = customer_column
# call base class init
TreeViewTooltips_gtk3.__init__(self)
def get_tooltip(self, column,cust_col,path):
"""By checking both column and path we have a cell-based tooltip"""
model = view.get_model()
customer = model[path][2]
if column is cust_col:
"""here there is lot of information on row"""
return '<big>%s %s</big>\n<i>%s</i>' % (customer.fname,
customer.lname,
customer.notes)
else:
"""here basic data only !!!!"""
return ('<big><u>Generic Column Tooltip</u></big>\n'
'Unless otherwise noted, all\n phone number is %s ') % customer.phone
# Here's our customer
class Customer:
def __init__(self, fname, lname, phone, notes):
self.fname = fname
self.lname = lname
self.phone = phone
self.notes = notes
# create a bunch of customers
customers = []
for fname, lname, phone, notes in [
('Joe', 'Schmoe', '555-1212', 'Likes to Morris dance.'),
('Jane', 'Doe', '555-2323',
'Wonders what the hell\nMorris dancing is.'),
('Phred', 'Phantastic', '900-555-1212', 'Dreams of Betty.'),
('Betty', 'Boop', '555-3434', 'Dreams in b&w.'),
('Red Sox', 'Fan', '555-4545',
"Still livin' 2004!\nEspecially after 2006.")]:
customers.append(Customer(fname, lname, phone, notes))
# Build our model and view
model = Gtk.ListStore(str, str, object)
for c in customers:
model.append(['%s %s' % (c.fname, c.lname), c.phone, c])
view = Gtk.TreeView(model)
# two columns, name and phone
cell = Gtk.CellRendererText()
cell.set_property('xpad', 20)
namecol = Gtk.TreeViewColumn('Customer Name', cell, text=0)
namecol.set_min_width(200)
view.append_column(namecol)
cell = Gtk.CellRendererText()
phonecol = Gtk.TreeViewColumn('Phone', cell, text=1)
view.append_column(phonecol)
# finally, connect the tooltip, specifying the name column as the
# column we want the tooltip to popup over.
tips = DemoTips_Gtk3(namecol)
tips.add_view(view)
# We're going to demonstrate enable/disable. First we need a
# callback function to connect to the toggled signal.
def toggle(button):
if button.get_active():
tips.disable()
else:
tips.enable()
# create a checkbutton and connect our handler
check = Gtk.CheckButton('Check to disable view tooltips')
check.connect('toggled', toggle)
check.set_tooltip_markup('This is a standard Gtk tooltip.\n'
'Compare me to the tooltips above.')
# create a VBox to pack the view and checkbutton
vbox = Gtk.VBox()
vbox.pack_start(view,False,False,2)
vbox.pack_start(check,False,False,2)
vbox.show_all()
# pack the vbox into a simple dialog and run it
dialog = Gtk.Dialog('TreeViewTooltips Demo')
tips.dialog = dialog #give tips the main window reference
close = dialog.add_button(Gtk.STOCK_CLOSE,Gtk.ResponseType.NONE)
# add a tooltip for the close button
close.set_tooltip_markup('Click to end the demo.')
dialog.set_default_size(400,400)
dialog.vbox.pack_start(vbox,False,False,2)
dialog.run()

Python Tkinter instance has no attribute 'tk'

AttributeError: MyGUI instance has no attribute 'tk'
Also, how do I make the created window have a fixed size and not be able to resize with the mouse? Or after changing label value by clicking on button.
My code:
from Tkinter import*
class MyGUI(Frame):
def __init__(self):
self.__mainWindow = Tk()
#lbl
self.labelText = 'label message'
self.depositLabel = Label(self.__mainWindow, text = self.labelText)
#buttons
self.hi_there = Button(self.__mainWindow)
self.hi_there["text"] = "Hello",
self.hi_there["command"] = self.testeo
self.QUIT = Button(self.__mainWindow)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
#place on view
self.depositLabel.pack()
self.hi_there.pack() #placed in order!
self.QUIT.pack()
#What does it do?
mainloop()
def testeo(self):
self.depositLabel['text'] = 'c2value'
print "testeo"
def depositCallBack(self,event):
self.labelText = 'change the value'
print(self.labelText)
self.depositLabel['text'] = 'change the value'
myGUI = MyGUI()
What's wrong?
Thanks
You should invoke the super constructor for Frame. Not sure, but I guess this will set the tk attribute that the quit command relies on. After that, there's no need to create your own Tk() instance.
def __init__(self):
Frame.__init__(self)
# self.__mainWindow = Tk()
Of course, you will also have to change the constructor calls for your widgets accordingly, e.g.,
self.hi_there = Button(self) # self, not self.__mainWindow
or better (or at least shorter): set all the attributes directly in the constructors:
self.hi_there = Button(self, text="Hello", command=self.testeo)
Also add self.pack() to your constructor.
(Alternatively, you could change the quit command to self.__mainWindow.quit, but I think the above is better style for creating Frames, see e.g. here.)
This error typically means you are calling SomeTKSuperClass.__init__ and forgetting the first parameter, which must be self. Remember that __init__ is a class method (static function) in this context, not an instance method, which means that you must explicitly pass it self.

Set default value for dynamic choice field

I have a form that asks the user to enter in their zip code. Once they do it sends them to another form where there is a field called 'pickup_date'. This gets the value of the zip from the previous field and gets all of the available pickup_dates that match that zip code into a ChoiceField. I set all of this within the init of the model form.
def __init__(self,*args,**kwargs):
super(ExternalDonateForm,self).__init__(*args,**kwargs)
if kwargs:
zip = kwargs['initial']['zip']
self.fields['pickup_date'] = forms.ChoiceField(choices = self.get_dates(zip))
elif self.errors:
zip = self.data['zip']
self.fields['pickup_date'] = forms.ChoiceField(choices = self.get_dates(zip))
The problem I have is when there are other errors on the form. I use the elif self.errors to regenerate the possible choices but it doesn't default to the original selected option. It goes back and defaults to the first choice. How can I make it so it's default option on form errors is what was originally posted?
Change self.fields['pickup_date'] to self.fields['pickup_date'].initial and see if that helps.
I got it to work after playing around for a while. Above, I was setting all the dynamic choices with a get_dates() function that returned a tuple. Instead of doing that I returned a field object like this using a customized ModelChoiceField instead of a regular ChoiceField....
class MyModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return obj.date.strftime('%a %b %d, %Y')
Dates function
def get_dates(self,zip):
routes = Route.objects.filter(zip=zip).values_list('route',flat=True)
pickups = self.MyModelChoiceField(queryset = PickupSchedule.objects.filter(
current_count__lt=F('specials'),
route__in=routes,
).order_by('date')
)
if not pickups:
pickups = (('----','No Pickups Available At This Time'),)
return pickups
in the init i set the value for self.fields['pickup_date'] like so..
self.fields['pickup_date'] = self.get_dates(zip)