更新时绑定到StringVar的Tkinter Label落后一键

2022-01-16 00:00:00 python tkinter label refresh listbox

问题描述

我在这里遇到的问题是,当我单击 Listbox 中的不同文件名时,Label 会在我的任何内容后面单击更改值m 当前点击.

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.

我在这里错过了什么?

import Tkinter as tk

class TkTest: 

    def __init__(self, master):

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

        # Set up a list box containing 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()


解决方案

问题与 Tk 的基本设计有关.简短的版本是,特定小部件上的绑定在小部件的默认类绑定之前触发.它是在类绑定中更改列表框的选择.这正是您所观察到的——您看到的是当前点击之前的选择.

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.

最好的解决方案是绑定到虚拟事件 <<ListboxSelect>> ,该事件在选择更改后触发.其他解决方案(Tk 独有的以及赋予它一些令人难以置信的功能和灵活性的原因)是修改应用绑定的顺序.这包括将小部件绑定标签移动到类绑定标签之后,或者在类绑定标签之后添加一个新的绑定标签并将其绑定到该类.

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.

由于绑定到 <<ListboxSelect>> 是更好的解决方案,我不会详细介绍如何修改绑定标签,尽管它很简单,而且我认为有据可查.

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.

相关文章