我正在尝试使用 python Tkinter 编写一个 GUI 应用程序,我遇到了这个问题,我的主要问题是,在关闭因按下打开按钮而打开的文件资源管理器后,是什么使以下代码中的按钮保持按下状态(或按下) .
我阅读了问题this和this,但我仍然无法找出这种行为背后的原因。
这是一个最小的工作代码来说明我的问题和我的代码结构。
import tkinter as tk
import tkinter.filedialog as fd
class OpenSection:
def __init__(self, parent):
self.parent = parent
def initFrame(self):
self.frmFrame = tk.Frame(self.parent)
def createComponenets(self):
self.btnOpenFile = tk.Button(self.frmFrame, text="OPEN")
def loacateComponents(self):
self.btnOpenFile.pack(side="left")
def constructFrame(self):
self.createComponenets()
self.loacateComponents()
def makeObjAvailable(self):
self.frmFrame.btnOpenFile = self.btnOpenFile
def createSection(self):
self.initFrame()
self.constructFrame()
self.makeObjAvailable()
return self.frmFrame
class OpenSectionFunc():
def askOpenFileNameCmd(self):
path = fd.askopenfilename(initialdir="/", title="Select Your File",filetypes=
(("Excel files", "*.xlsx"), ("Excel Macro enabled files", "*.xlsm")))
# return "break"
class MainWindow:
def __init__(self, title, dimension):
self.mainWinodw = tk.Tk()
self.mainWinodw.title(title)
self.mainWinodw.geometry(dimension)
def createComponents(self):
self.frmOpenSection = OpenSection(self.mainWinodw).createSection()
def locateComponents(self):
self.frmOpenSection.pack(side="top", expand=0, fill="x")
def constructMainWindow(self):
self.createComponents()
self.locateComponents()
def start(self):
self.mainWinodw.mainloop()
mainWinodw = MainWindow("tk", "400x600")
mainWinodw.constructMainWindow()
mainWinodw.frmOpenSection.btnOpenFile.bind("<Button-1>", lambda event:OpenSectionFunc().askOpenFileNameCmd())
mainWinodw.start()
我知道取消注释
askOpenFileNameCmd(self)
的最后一行可以解决问题(如何?)但首先我想清楚地解释问题背后的原因,然后我想问的是正在使用return "break"
要解决问题,一个可接受的解决方案或问题的根源是我错误地构建了我的代码,对我来说重写我的代码更好,因为我喜欢找到更合乎逻辑的解决方案,所以我不必处理此类问题,如果我的代码增长了。
当您将
<Button-1>
绑定到按钮时,它似乎破坏了默认的按钮按下行为。从事件处理程序返回“break”会阻止 Tkinter 将事件传播到其他处理程序。在您的情况下,这会阻止默认按钮单击处理程序运行,从而解决问题。或者,您可以使用按钮的 command
属性,因为这是将按钮单击绑定到按钮的预期方法。
至于代码的结构,我认为可以通过直接子类化 tkinter 小部件并删除一些不必要的方法来使其更清晰。我会做这样的事情:
import tkinter as tk
import tkinter.filedialog as fd
class OpenSection(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.createComponents()
self.locateComponents()
def createComponents(self):
self.btnOpenFile = tk.Button(self, text="OPEN", command = self.askOpenFileNameCmd)
def locateComponents(self):
self.btnOpenFile.pack(side = "left")
def askOpenFileNameCmd(self):
path = fd.askopenfilename(initialdir="/", title="Select Your File",filetypes=
(("Excel files", "*.xlsx"), ("Excel Macro enabled files", "*.xlsm")))
class MainWindow(tk.Tk):
def __init__(self, title, dimension):
tk.Tk.__init__(self)
self.title(title)
self.geometry(dimension)
self.createComponents()
self.locateComponents()
def createComponents(self):
self.frmOpenSection = OpenSection(self)
def locateComponents(self):
self.frmOpenSection.pack(side="top", expand=0, fill="x")
app = MainWindow("tk", "400x600")
app.mainloop()
OpenSection
现在是 tk.Frame
的子类,因此 OpenSection
将像框架一样工作。 initFrame
、constructFrame
和 createSection
方法都已合并到 __init__
方法中,因为它们实际上不需要分开。该按钮现在使用 command
属性而不是 bind
,并且按钮命令函数已移至与按钮相同的类中,因此可以更轻松地查看发生的情况。 MainWindow
已进行类似清理。