[Tutor] events and popup menus
Peter Otten
__peter__ at web.de
Thu May 3 12:30:13 CEST 2012
Chris Hare wrote:
> I have four images in a frame. I want to pop up a menu when the user
> right clicks on an image, and when they choose an option from the menu,
> execute the action.
>
> I can create the popup menu, and bind it to the image. However, what I
> can't figure out is how to detect in the popup menu code which image fired
> the event so I can do the right thing (like display a larger version of
> the image, etc.)
>
> # create a menu
> self.popup = Menu(self.pictureWindow, tearoff=0)
> self.popup.add_command(label="Change Picture",
> command=self.selectPicture) self.popup.add_command(label="Make Primary",
> command=self.selectPicture) self.popup.add_command(label="Large View",
> command=self.selectPicture)
You should have a different callback for every menu item:
self.popup.add_command(label="Change Picture", command=self.change_picture)
...
self.popup.add_command(label="Large View", command=self.large_view)
> self.picture1.bind("<Button-1>", self.do_popup)
>
> def do_popup(self,event):
> # display the popup menu
> try:
> self.popup.tk_popup(event.x_root, event.y_root, 0)
>
> finally:
> # make sure to release the grab (Tk 8.0a1 only)
> self.popup.grab_release()
>
> Thanks for the advice!
You can remember the widget from do_popup()'s event argument
def do_popup(self, event):
self.current_picture = event.widget
...
and later refer to it in the menu callbacks
def select_picture(self):
picture = self.current_picture
...
I got a bit distracted struggling with PIL, therefore my "self-contained
demo" got rather baroque. You may still find it useful:
$ cat tk_popup_demo.py
import sys
import Tkinter as tk
import ImageTk
import Image
current_label = None
def do_popup(event):
global current_label
current_label = event.widget
try:
popup.tk_popup(event.x_root, event.y_root, 0)
finally:
popup.grab_release()
def rotate_picture():
image = current_label.photoimage.image.rotate(90)
photoimage = ImageTk.PhotoImage(image)
photoimage.image = image
current_label.photoimage = current_label["image"] = photoimage
def flip_picture():
print "flip picture"
def load_image(filename, maxsize=(500, 500), padcolor="#f80"):
image = Image.open(filename)
image.thumbnail(maxsize)
if image.size != maxsize:
padded_image = Image.new(image.mode, maxsize, color=padcolor)
maxx, maxy = maxsize
x, y = image.size
padded_image.paste(image, ((maxx-x)//2, (maxy-y)//2))
image = padded_image
assert image.size == maxsize
return image
root = tk.Tk()
picturefiles = sys.argv[1:4]
for i, filename in enumerate(picturefiles):
image = load_image(filename)
photoimage = ImageTk.PhotoImage(image)
photoimage.image = image
label = tk.Label(root, image=photoimage)
label.photoimage = photoimage
label.grid(row=0, column=i)
label.bind("<Button-3>", do_popup)
popup = tk.Menu(root, tearoff=0)
popup.add_command(label="Rotate", command=rotate_picture)
popup.add_command(label="Flip", command=flip_picture)
root.mainloop()
Invoke with a few picture names (all but the first three will be ignored):
$ python tk_popup_demo.py *.jpg
More information about the Tutor
mailing list