【问题标题】:Trouble binding events in TKinterTKinter 中的绑定事件问题
【发布时间】:2013-02-28 13:09:14
【问题描述】:

对于背景:我的大部分经验是 ruby​​/rails。我试图通过构建一个简单的 GUI 应用程序来帮助朋友,该应用程序更新 Excel 文件并且没有太多使用 Python 或 TKinter 的经验。目标是有一个简单的表单,用户输入一个数字,另一个表单显示一个下拉菜单。我决定将给定的数字存储在一个全局变量中,因为我在尝试在两个帧之间传递一个变量时遇到了麻烦。我无法同时设置全局变量并切换到第二帧。我遇到的其他问题/问题在## 标记的 cmets 中。

另外,如果有人对制作可以访问 MDB 或 excel 文件的跨平台应用程序的最佳方法有任何想法,我会全力以赴。这让我大吃一惊,这是多么困难。感谢您的帮助。

import Tkinter as tk

TITLE_FONT = ("Helvetica", 18, "bold")
ID_NUMBER = None

class StatusApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (EntryPage, StatusPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(EntryPage)

    def show_frame(self, c):
        '''Show a frame for the given class'''
        frame = self.frames[c]
        frame.tkraise()

class EntryPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent) 
        label = tk.Label(self, text="Enter ID:", font=TITLE_FONT)
        self.entry = tk.Entry(self)
        ## Using the lambda works to switch frames, but I need to be able to execute 
        ## multiple statements.
        # entry.bind('<Return>', lambda event: controller.show_frame(StatusPage))

        ## In examples I've seen, callback has been used without the empty parens, not sure
        ## why they're needed?
        self.entry.bind('<Return>', self.callback())
        label.pack(side="top", fill="x", pady=10)
        self.entry.pack()
        self.entry.focus_set()

    def callback(self):
        ## I noticed the following gets fired once the program starts
        print 'hello'

        ## For some reason it says that entry doesn't have the attribute 'set'. I don't
        ## understand this as I'm calling it like a method.
        self.entry.set('hello')

        ## Ultimately setting the global ID_NUMBER variable is one of the main goals of this
        ## function
        ID_NUMBER = self.entry.get()

        ## I haven't been able to switch frames from within this function, only w/ a lambda as
        ## seen on line 34.
        # show_frame(StatusPage())

class StatusPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent) 
        label = tk.Label(self, text="ID: ", font=TITLE_FONT)
        optionList = ('train', 'plane', 'boat')
        selected_opt = tk.StringVar()
        selected_opt.set(ID_NUMBER)
        menu = tk.OptionMenu(self, selected_opt, *optionList)
        button = tk.Button(self, text="Save", command=lambda: controller.show_frame(EntryPage))
        label.pack(side="top", fill="x", pady=10)
        menu.pack()
        button.pack()

if __name__ == "__main__":
    app = StatusApp()
    app.mainloop()

【问题讨论】:

    标签: python user-interface event-handling tkinter


    【解决方案1】:

    绑定的对象必须是对可调用函数的引用。 Lambda 经常在这种情况下使用,因为它会创建一个匿名函数并返回一个引用)。

    当您执行...bind(..., self.callback()) 时,您将在执行绑定语句时调用该函数。在代码中,您添加评论 ## I noticed the following gets fired once the program starts;这就是为什么。此函数调用的结果是与绑定相关联的内容。很多时候,在您的特定情况下,这是值None。您必须省略 ()

    在你写的代码cmets中

    ## For some reason it says that entry doesn't have the attribute 'set'. I don't
    ## understand this as I'm calling it like a method.
    self.entry.set('hello')
    

    是什么让您相信条目小部件具有set 方法?据我所知,没有任何文件提出这种说法。错误信息是正确的,入口小部件没有名为“set”的属性(函数在此上下文中被视为属性)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多