在按下按钮时执行功能,而不是在脚本运行时执行
Execute function when button is pressed, not when script runs
我想出了这个代码:
import tkinter
from tkinter.filedialog import askopenfilename
def browse():
inputfilename=askopenfilename()
return inputfilename
def fileManipulator(infile=browse(),outfile="C:\out\File.kml"):
#code that manipulates the file here
file.save(outfile)
root=tkinter.Tk()
browseButton=tkinter.Button(root,text="Browse",command=browse)
browseButton.pack()
fileButton=tkinter.Button(root,text="Manipulate file",command=fileManipulator)
fileButton.pack()
root.mainloop()
该代码为我提供了一个带有两个按钮的 GUI。 Browse 按钮应该让用户浏览输入文件。 Manipulate File 按钮应该处理该文件并将文件输出保存在某处。
我面临的问题是浏览 askopenfilename
函数在我 运行 发生时立即执行 script.That 因为我在 fileManipulator 的定义中调用该函数功能。我在 fileManipulator 中调用函数的原因显然是因为我想使用 askopenfilename returns 作为输入文件的路径。
是否有解决方法可以不立即执行 askopenfilename
,而是在按下 浏览 按钮时执行?
编辑: 我也不希望在按下 File Manipulator 按钮时再次执行 browse() 函数。
编辑: 对于更新的要求 -
Sorry, I should have added some more details. Your solutions work well in that the browse() function is not executing immediately now. However, apart from that, I also want that the GUI prompts the user only once with the Browse dialog box. In your solution, the user is prompted once when they press Browse, and another time when they press File Mnipulator. I also edited my question to reflect what I am looking for.
如果是这样,我想您可以定义某种 global
变量,它会在调用 browse()
时更新,然后改用它。如果全局变量是 None
或任何默认值,这意味着您是第一次调用 file Manipulate
,那么让您的函数调用 browse()
方法。例子-
import tkinter
from tkinter.filedialog import askopenfilename
inputfile = None
def browse():
global inputfile
inputfile=askopenfilename()
def fileManipulator(outfile="C:\out\File.kml"):
global inputfile
if inputfile is None:
browse()
#code that manipulates the file here
file.save(outfile)
root=tkinter.Tk()
browseButton=tkinter.Button(root,text="Browse",command=browse)
browseButton.pack()
fileButton=tkinter.Button(root,text="Manipulate file",command=fileManipulator)
fileButton.pack()
root.mainloop()
原始问题:
问题是函数的默认参数是在定义函数时执行的(而不是在调用函数时),这是像 Mutable Default Arguments[=60= 这样的 GOTCHA 的主要原因],还有你的问题。
如果您希望能够将 infile
作为参数发送,并且还能够使用 browse()
函数(如果未提供)。我建议您使用 **kwargs
。例子-
def fileManipulator(outfile="C:\out\File.kml",**kwargs):
if 'infile' in kwargs:
infile = kwargs['infile']
else:
infile = browse()
#code that manipulates the file here
file.save(outfile)
另一种更简单的方法是使用默认值,如 None
左右,然后如果 infile
是 None
,则使用 browse()
方法 -
def fileManipulator(infile=None,outfile="C:\out\File.kml"):
if infile is None:
infile=browse()
#code that manipulates the file here
file.save(outfile)
但这与您最初尝试的不同,因为如果您将函数调用为 - fileManipulator(infile=None)
,这将导致调用 browse()
函数。
最后,如果您不需要 infile
/ outfile
作为参数,请不要将它们定义为默认参数,而是在函数体中定义它们 -
def fileManipulator():
infile=browse()
outfile="C:\out\File.kml"
#code that manipulates the file here
file.save(outfile)
相关部分来自documentation -
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call.
我遇到了同样的问题,这是我的解决方案:
self.button = Button(self, text="Preview", command=lambda: runFunction(arg0,arg1,arg2))
我想出了这个代码:
import tkinter
from tkinter.filedialog import askopenfilename
def browse():
inputfilename=askopenfilename()
return inputfilename
def fileManipulator(infile=browse(),outfile="C:\out\File.kml"):
#code that manipulates the file here
file.save(outfile)
root=tkinter.Tk()
browseButton=tkinter.Button(root,text="Browse",command=browse)
browseButton.pack()
fileButton=tkinter.Button(root,text="Manipulate file",command=fileManipulator)
fileButton.pack()
root.mainloop()
该代码为我提供了一个带有两个按钮的 GUI。 Browse 按钮应该让用户浏览输入文件。 Manipulate File 按钮应该处理该文件并将文件输出保存在某处。
我面临的问题是浏览 askopenfilename
函数在我 运行 发生时立即执行 script.That 因为我在 fileManipulator 的定义中调用该函数功能。我在 fileManipulator 中调用函数的原因显然是因为我想使用 askopenfilename returns 作为输入文件的路径。
是否有解决方法可以不立即执行 askopenfilename
,而是在按下 浏览 按钮时执行?
编辑: 我也不希望在按下 File Manipulator 按钮时再次执行 browse() 函数。
编辑: 对于更新的要求 -
Sorry, I should have added some more details. Your solutions work well in that the browse() function is not executing immediately now. However, apart from that, I also want that the GUI prompts the user only once with the Browse dialog box. In your solution, the user is prompted once when they press Browse, and another time when they press File Mnipulator. I also edited my question to reflect what I am looking for.
如果是这样,我想您可以定义某种 global
变量,它会在调用 browse()
时更新,然后改用它。如果全局变量是 None
或任何默认值,这意味着您是第一次调用 file Manipulate
,那么让您的函数调用 browse()
方法。例子-
import tkinter
from tkinter.filedialog import askopenfilename
inputfile = None
def browse():
global inputfile
inputfile=askopenfilename()
def fileManipulator(outfile="C:\out\File.kml"):
global inputfile
if inputfile is None:
browse()
#code that manipulates the file here
file.save(outfile)
root=tkinter.Tk()
browseButton=tkinter.Button(root,text="Browse",command=browse)
browseButton.pack()
fileButton=tkinter.Button(root,text="Manipulate file",command=fileManipulator)
fileButton.pack()
root.mainloop()
原始问题:
问题是函数的默认参数是在定义函数时执行的(而不是在调用函数时),这是像 Mutable Default Arguments[=60= 这样的 GOTCHA 的主要原因],还有你的问题。
如果您希望能够将 infile
作为参数发送,并且还能够使用 browse()
函数(如果未提供)。我建议您使用 **kwargs
。例子-
def fileManipulator(outfile="C:\out\File.kml",**kwargs):
if 'infile' in kwargs:
infile = kwargs['infile']
else:
infile = browse()
#code that manipulates the file here
file.save(outfile)
另一种更简单的方法是使用默认值,如 None
左右,然后如果 infile
是 None
,则使用 browse()
方法 -
def fileManipulator(infile=None,outfile="C:\out\File.kml"):
if infile is None:
infile=browse()
#code that manipulates the file here
file.save(outfile)
但这与您最初尝试的不同,因为如果您将函数调用为 - fileManipulator(infile=None)
,这将导致调用 browse()
函数。
最后,如果您不需要 infile
/ outfile
作为参数,请不要将它们定义为默认参数,而是在函数体中定义它们 -
def fileManipulator():
infile=browse()
outfile="C:\out\File.kml"
#code that manipulates the file here
file.save(outfile)
相关部分来自documentation -
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call.
我遇到了同样的问题,这是我的解决方案:
self.button = Button(self, text="Preview", command=lambda: runFunction(arg0,arg1,arg2))