mommermi
mommermi

Reputation: 1052

Tkinter click event does not trigger; keyboard does

I found this neat code here that uses Tkinter to display a series of images. I extended the code to use the 'z' and 'x' keys to browse through the images and 'q' to quit. Also, I would like to be able to click on the individual frames and obtain the image coordinates of where I clicked. While the keyboard interaction works just fine, the mouse click event does not get triggered. I wonder why that is, since the key strokes are triggered just fine.

This is the code I have:

#!/usr/bin/env python
from Tkinter import *
import Image, ImageTk
import os, sys

class Clicker:
    def __init__(self, master, filelist):
        self.top = master
        self.files = filelist
        self.index = 0

        #display first image
        filename = filelist[0]
        if not os.path.exists(filename):
            print "Unable to find %s" % filename
            self.top.quit()

        self.title = Label(text=os.path.basename(filename))
        self.title.pack()

        im = Image.open(filename)
        self.tkimage = ImageTk.PhotoImage(im, palette=256)

        self.lbl = Label(master, image=self.tkimage)
        self.lbl.pack(side='top')

        # the button frame
        fr = Frame(master)
        fr.pack(side='top', expand=1, fill='both')
        back = Button(fr, text="back", command=lambda : self.nextframe(-1))
        back.grid(row=0, column=0, sticky="w", padx=4, pady=4)

        self.ilabel = Label(fr, text="image number: %d/%d" % 
                            (self.index+1, len(self.files)))
        self.ilabel.grid(row=0, column=1, sticky="e", pady=4)

        self.evar = IntVar()
        self.evar.set(1)

        next = Button(fr, text="next", command=lambda : self.nextframe(1))
        next.grid(row=0, column=3, sticky="e", padx=4, pady=4)

        # events 
        fr.focus_set()
        fr.bind("<Key>", self.key)
        fr.bind("<Button 1>", self.left_click)


    def left_click(self, event):
        print (event.x,event.y)


    def key(self, event):
        if event.char == 'z':
            # previous frame
            self.nextframe(-1)
        elif event.char == 'x':
            # next frame
            self.nextframe(1)
        elif event.char == 'q':
            # quit
            self.top.quit()

    def getImage(self, filename):
        im = Image.open(filename)
        return im

    def nextframe(self,i=1, imgnum=-1):
        if imgnum == -1:
            self.index += i
        else:
            self.index = imgnum - 1
        if self.index >= len(self.files):
            self.index = 0
        elif self.index < 0:
            self.index = len(self.files) - 1
        filename = self.files[self.index]
        if not os.path.exists(filename):
            print "Unable to find %s" % filename
            self.top.quit()
        self.title.configure(text=os.path.basename(filename))
        self.evar.set(self.index+1)

        self.ilabel.configure(text="image number: %d/%d" % 
                              (self.index+1, len(self.files)))

        im = self.getImage(filename)
        self.tkimage.paste(im)

    def getimgnum(self, event=None):
        self.nextframe(imgnum=self.evar.get())



# --------------------------------------------------------------------

if __name__ == "__main__":

    if not sys.argv[1:]:
        print "Usage: click.py images*"
        sys.exit()
    filelist = sys.argv[1:]

    root = Tk()
    app = Clicker(root, filelist)
    root.mainloop()

The code should work with any set of images, all of which have to have the same dimensions.

Edit: Interestingly, I can get the cursor position on a key stroke but not on a mouse click.

Upvotes: 2

Views: 121

Answers (1)

mommermi
mommermi

Reputation: 1052

It seems like I found the answer myself:

If I replace the Frame with a Canvas, I am able to trigger a mouse click event. I am not sure why that is the case, but it works.

Upvotes: 1

Related Questions