开发者

Tkinter Label bound to StringVar is one click behind when updating

开发者 https://www.devze.com 2023-01-01 04:53 出处:网络
The problem I\'m running into here is that, when I click on the different file names in the Listbox, the Label changes value one click behind whatever I\'m currently clicking on.

The problem I'm running into here is that, when I click on the different file names in the Listbox, the Label changes value one click behind whatever I'm currently clicking on.

What am I missing here?

import Tkinter as tk

class TkTest: 

    def __init__(self, master):

        self.fraMain = tk.Frame(master)
        self.fraMain.pack()

        # Set up a list box con开发者_Go百科taining all the paths to choose from
        self.lstPaths = tk.Listbox(self.fraMain)
        paths = [
            '/path/file1',
            '/path/file2',
            '/path/file3',
        ]
        for path in paths:
            self.lstPaths.insert(tk.END, path)
        self.lstPaths.bind('<Button-1>', self.update_label)
        self.lstPaths.pack()

        self.currentpath = tk.StringVar()
        self.lblCurrentPath = tk.Label(self.fraMain, textvariable=self.currentpath)
        self.lblCurrentPath.pack()

    def update_label(self, event):
        print self.lstPaths.get(tk.ACTIVE),
        print self.lstPaths.curselection()
        self.currentpath.set(self.lstPaths.get(tk.ACTIVE))

root = tk.Tk()
app = TkTest(root)
root.mainloop()


The problem has to do with the fundamental design of Tk. The short version is, bindings on specific widgets fire before the default class bindings for a widget. It is in the class bindings that the selection of a listbox is changed. This is exactly what you observe -- you are seeing the selection before the current click.

The best solution is to bind to the virtual event <<ListboxSelect>> which is fired after the selection has changed. Other solutions (unique to Tk and what gives it some of its incredible power and flexibility) is to modify the order that the bindings are applied. This involves either moving the widget bindtag after the class bindtag, or adding a new bindtag after the class bindtag and binding it to that.

Since binding to <<ListboxSelect>> is the better solution I won't go into details on how to modify the bindtags, though it's straight-forward and I think fairly well documented.

0

精彩评论

暂无评论...
验证码 换一张
取 消