Tkinter 通过菜单栏按钮存储文件名

Posted

技术标签:

【中文标题】Tkinter 通过菜单栏按钮存储文件名【英文标题】:Tkinter store filename through menubar button 【发布时间】:2017-01-16 14:28:17 【问题描述】:

我创建了一些函数,可以在我用 tkinter 制作的 GUI 中显示 csv 文件的图形和表格。

我有一个menubar,带有一个 import 按钮、一个 plot 按钮和一个 table 按钮。 plottable按钮可以分别成功绘制csv文件的图形和表格。

我想做的是,当用户选择 import 按钮时,他们会选择他们选择的文件。然后,如果他们碰巧选择了 plot 按钮,绘图功能将作用于他们从 import 中选择的文件。此外,如果他们碰巧选择了 table 按钮,则 table 函数将作用于他们从 import 中选择的文件。

我创建了一个名为openfile() 的文件打开函数,它会记住打开的文件的名称。

问题是我不知道如何使用menubaropenfile() 这样当点击import 按钮时,我的应用程序会存储文件名。

关于我将如何进行此操作的任何提示?

这是我为menubaropenfile() 编写的代码:

def openfile():
    name= askopenfilename() 
    return (name[19:])

class MyApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        tk.Tk.wm_title(self, "MyApp")
        # main frame
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

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

        # creates the menubar at the top of the window
        menubar = tk.Menu(container)

        # import menu for importing csv files, initializes a file opening function (tbd)
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Import a CSV File", command = file_openerfunction)
        menubar.add_cascade(label= "Import", menu=filemenu)

        # plot menu for creating graphs and figures
        Plot = tk.Menu(menubar, tearoff =0 )
        Plot.add_command(label="Plot My CSV File", command= popupgraph)
        menubar.add_cascade(label="Plot", menu=Plot)

        # table menu for viewing data in a table
        table = tk.Menu(menubar, tearoff = 0)
        table.add_command(label="View MY CSV File", command = table)
        table.add_cascade(label = "View Data", menu = table)

        tk.Tk.config(self, menu=table)
        ....
        ....

【问题讨论】:

【参考方案1】:

首先,我建议您采用面向对象的方法来拆分每个组件的行为。

这样,您将拥有一个 App 类,您将在其中初始化应用程序的主要组件:

class App(tk.Tk):

    def __init__(self,parent):
        Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        ...

        ...
        # Menubar
        self.menubar = MyMenuBar(self)

        # Filemenu
        self.filemenu = MyFileMenu(self, menubar)

        # Plot
        self.plot = MyPlot(self, menubar)

        # The rest for all the other components
        ...

    def get_import_filename(self):
        # Ask the child for the filename and return it
        return self.filemenu.get_filename()

然后定义你的每一个对象:

class MyPlot(tk.Menu):
      def __init__(self, parent, menubar):
           tk.Menu.__init__(self, menubar, tearoff=0)
           self.parent = parent
           self.initialize()

      def initialize(self):
          self.add_command(label="Plot My CSV File", command= self.popupgraph)  

      def popupgraph(self):
          # Ask the parent for the filename
          filename = self.parent.get_import_filename()
          # Do whatever with the filename...like open a file

class MyFileMenu(tk.Menu):
      def __init__(self, parent, menubar):
           tk.Menu.__init__(self, menubar, tearoff=0)
           self.parent = parent
           self.initialize()
      def initialize(self):
          self.add_command(label="Import a CSV File", command = file_opener)
      def file_opener(self):
          # Your file opener function goes here
          ...
          # At the end, save the imported file:
          self.filename = filename
      def get_filename(self):
          return self.filename

最后,让 main 运行它:

def main():
    app = App(None)
    app.title('Auto login')
    app.mainloop()

if __name__ == "__main__":
    main()

【讨论】:

非常感谢!这很好用。我将听取您的建议并将我的代码更改为更面向对象的方法。关于文件打开问题,我找到了一个非常简单的方法让 GUI 记住选择的文件:将选择的文件存储在列表中,然后在列表元素上调用 popupgraph。 为什么你的例子有两个名为MyPlot的类? @BryanOakley 拼写错误。对不起。立即编辑。【参考方案2】:

otorrillas 解决方案完美运行。

我找到了另一种解决此问题的简单方法。为了让 GUI 记住从 import 中选择的文件,请将文件名附加到列表中。然后,在列表元素上调用popupgraph()viewcsv()。这是我的文件打开功能的新代码。

file_list = []

def openfile():
    name= askopenfilename() 
    file_list.append(name[19:])

【讨论】:

【参考方案3】:

我不明白您尝试做某些事情的方式(或为什么在某些情况下您会这样做),但这里有一个可运行的示例,它创建了一个简单的 Choices简单 tkinter 应用程序窗口左上角的级联菜单。希望你';;能够适应并将其集成到您的项目代码中。

我创建了用于导入 CSV 文件的命令 file_openerfunction,这是一个类方法并让它调用 openfile() 函数,因为这样返回的值(文件名)可以作为属性存储在 self.filename 中。这将允许它在创建后用于其他命令选择(因此他们将知道要操作哪个文件)。

try:
    import Tkinter as tk
    from tkFileDialog import askopenfilename
except ModuleNotFoundError:   $ Python 3
    import tkinter as tk
    from tkinter.filedialog import askopenfilename

def openfile():
    name = askopenfilename()
    return name[19:]

class MyApp(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.master.title("MyApp")

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

        top = self.winfo_toplevel()
        self.menubar = tk.Menu(top)
        top['menu'] = self.menubar

        self.submenu = tk.Menu(self.menubar)
        self.menubar.add_cascade(label='Choices', menu=self.submenu)

        self.submenu.add_command(label="Import a CSV File",
                                 command=self.file_openerfunction)
        self.submenu.add_command(label="Plot My CSV File",
                                 command=self.popupgraph)
        self.submenu.add_command(label="View MY CSV File",
                                 command=self.table)

    def file_openerfunction(self):
        self.filename = openfile()

    def popupgraph(self): pass
    def table(self): pass

app = MyApp()
app.mainloop()

我还建议您阅读并关注PEP 8 - Style Guide for Python Code,这将有助于标准化您编写的代码并提高其可读性。

【讨论】:

以上是关于Tkinter 通过菜单栏按钮存储文件名的主要内容,如果未能解决你的问题,请参考以下文章

画布上的 tkinter 菜单栏

使用 Tkinter 中的菜单栏在页面之间切换

Tkinter 菜单栏

如何在 Tkinter 中创建垂直菜单栏?

Tkinter实现窗口菜单栏

如何为 pygame 创建这个 tkinter 菜单栏