即使在运行回调函数后,Tkinter 按钮仍保持按下状态

问题描述 投票:0回答:1

我正在尝试使用 python Tkinter 编写一个 GUI 应用程序,我遇到了这个问题,我的主要问题是,在关闭因按下打开按钮而打开的文件资源管理器后,是什么使以下代码中的按钮保持按下状态(或按下) .

我阅读了问题thisthis,但我仍然无法找出这种行为背后的原因。

这是一个最小的工作代码来说明我的问题和我的代码结构。

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" 
要解决问题,一个可接受的解决方案或问题的根源是我错误地构建了我的代码,对我来说重写我的代码更好,因为我喜欢找到更合乎逻辑的解决方案,所以我不必处理此类问题,如果我的代码增长了。

python python-3.x tkinter binding tkinter-button
1个回答
0
投票

当您将

<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
已进行类似清理。

© www.soinside.com 2019 - 2024. All rights reserved.