在 tkinter GUI 中传递变量的正确方法

KBr*_*ggs 1 user-interface tkinter python-2.7

我正在尝试编写一个简单的 GUI 来绘制csv文件中的数据,我将其读入 pandas DataFrame。我对 GUI 编程完全陌生,我很难理解像 Tkinter 这样的事件驱动设置。

作为一个简单的练习,我想成立了两个按钮,一个打开一个文件,并在读取DataFrame,而另一个打印出所产生的DataFrame。我的第一次天真尝试没有奏效:

import pandas as pd
import tkFileDialog
import Tkinter as tk

def open_events_db():
    file_path_string = tkFileDialog.askopenfilename()
    eventsdb = pd.read_csv(file_path_string,encoding='utf-8')
    return eventsdb

def print_events_db(eventsdb):
    print eventsdb

def main():
    root=tk.Tk()
    eventsdb = tk.Button(text='File Open', command=open_events_db).pack(fill=tk.X)
    tk.Button(text='Print DB', command=lambda:print_events_db(eventsdb)).pack(fill=tk.X)
    tk.mainloop()


if __name__=="__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

我可以很好地读入文件并打开它,但事后看来显然我无法eventsdb从文件打开按钮返回并将其作为打印按钮的参数。

不过,我认为在该数据库上运行按钮并不是不合理的,那么在 GUI 中传递变量的正确方法是什么?

Bry*_*ley 5

从按钮和事件处理程序调用的函数不返回它们的数据。相反,他们必须设置全局变量或类属性。

def open_events_db():
    global eventsdb
    file_path_string = tkFileDialog.askopenfilename()
    eventsdb = pd.read_csv(file_path_string,encoding='utf-8')

def print_events_db():
    global eventsdb
    print eventsdb

...
tk.Button(text='Print DB', command=print_events_db).pack(fill=tk.X)
Run Code Online (Sandbox Code Playgroud)

依赖全局变量通常被认为是糟糕的编程。由于 Python 是一种面向对象的语言,因此将您的应用程序编写为一个类是有意义的。然后您将使用实例属性而不是全局变量。

import Tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        open_button = tk.Button(text='File Open', command=self.open_events_db)
        print_button = tk.Button(text='Print DB', command=self.print_events_db)

        open_button.pack(fill=tk.X)
        print_button.pack(fill=tk.X)

    def open_events_db(self):
        file_path_string = tkFileDialog.askopenfilename()
        self.eventsdb = pd.read_csv(file_path_string,encoding='utf-8')

    def print_events_db():
        print self.eventsdb

def main():
    root=tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

if __name__=="__main__":
    main()
Run Code Online (Sandbox Code Playgroud)