【问题标题】:Python Tkinter File Dialog event order, returning string from button clickPython Tkinter 文件对话框事件顺序,从按钮单击返回字符串
【发布时间】:2015-04-26 19:32:38
【问题描述】:

大家下午好,

我不想使用命令行或在 Python 中硬编码文件名,而是希望有一个单独的类,我可以在任何其他 Python 程序中使用它,它允许使用 Tkinter 文件对话框选择文件。这是我目前所拥有的:

import Tkinter as tk
import tkFileDialog
import tkFont

###################################################################################################
class MyFileDialog(tk.Frame):

    # class level variables #######################################################################
    my_form = tk.Tk()                   # declare form
    my_button = tk.Button(my_form)      # declare button
    chosen_file = ""

    # constructor #################################################################################
    def __init__(self):
                                            # create button event
        self.my_button.configure(text = "press here", command = self.on_my_button_click)
        self.my_button.pack()               # add button to form

        # make the button font bigger so I don't have to squint
        updated_font = tkFont.Font(font = self.my_button['font'])
        updated_font['size'] = int(float(updated_font['size']) * 1.6)
        self.my_button.configure(font = updated_font)

    ###############################################################################################
    def on_my_button_click(self):
        self.chosen_file = tkFileDialog.askopenfilename()       # get chosen file name
        return

    ###############################################################################################
    def get_chosen_file(self):
        return self.chosen_file                 # return chosen file name

###################################################################################################
if __name__ == "__main__":
    my_file_dialog = MyFileDialog()

    my_file_dialog.my_form.mainloop()

    # I need to get the chosen file here, when the file is chosen, NOT when the window is closed !!
    # please help !!

    print my_file_dialog.get_chosen_file()    # this does not print until the window is closed !!!

此代码的当前问题是(如最后的注释所示)测试代码在窗口关闭之前不会收到所选的文件名,但是我需要测试代码在文件关闭时接收文件名被选中。

我应该提到,在生产使用中,测试代码将完全位于一个不同的文件中,该文件将导入和实例化这个类,因此应该保持类的模块化。有人有解决方案吗?请帮忙!

【问题讨论】:

  • 由于与 OpenCV 的兼容性,我忘了说我目前使用的是 Python 2.7.X

标签: python user-interface button tkinter


【解决方案1】:

简而言之,mainloop() 会阻止所有其他调用,直到窗口被销毁(更多信息:Tkinter understanding mainloop)。这就是为什么您的 print 语句一直等到窗口关闭的原因。

if __name__ == "__main__":

    my_file_dialog = MyFileDialog()
    my_file_dialog.my_form.mainloop()

    # this line will not run until the mainloop() is complete.
    print my_file_dialog.get_chosen_file()

一个简单的解决方案可能是将您的chosen_file 变量更改为tk.StringVar(),然后您可以将callback 方法附加到该变量。

import Tkinter as tk
import tkFileDialog
import tkFont

class MyFileDialog(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)

        self.master = master

        # class variables
        self.chosen_file = tk.StringVar()

        # ui elements
        self.my_button = tk.Button(self)

        # configure button
        self.my_button.configure(\
            text = "press here", command = self.on_my_button_click)

        # make button font bigger
        # ...

        # add button to frame
        self.my_button.pack()

        # attach a callback to chosen_file with trace
        self.chosen_file.trace("w", self.callback)

    # execute this method whenever chosen_file gets written
    def callback(self, *args):

        print("MyFileDialog: chosen_file is %s" % self.chosen_file.get())

    def on_my_button_click(self):

        f = tkFileDialog.askopenfilename()

        # set chosen_file here to trigger callback (wherever it is)
        self.chosen_file.set(f)


if __name__ == "__main__":

    root = tk.Tk()
    app = MyFileDialog(root).pack()
    root.mainloop()

请注意,您不必将 callback 方法放在您的 MyFileDialog 类中:您可以在实例化 MyFileDialog 对象后在另一个类中轻松创建回调。

class MyApp(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)

        self.master = master

        self.mfd = MyFileDialog(master)
        self.mfd.pack()

        # attach callback to chosen_file from MyFileDialog
        self.mfd.chosen_file.trace("w", self.callback)

    def callback(self, *args):

        print("MyApp: chosen_file is %s" % self.mfd.chosen_file.get())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多