Tkinter 按钮命令在运行程序时激活?

Posted

技术标签:

【中文标题】Tkinter 按钮命令在运行程序时激活?【英文标题】:Tkinter button command activates upon running program? 【发布时间】:2011-04-11 21:35:05 【问题描述】:

我正在尝试制作一个构建检索表单,但按钮似乎有问题...我是 Python/tkinter GUI 编程(以及一般的 GUI 编程)的新手,并借用了 Hello 的骨架World 应用程序,并以此为基础。

在下面的代码中,我设置了“浏览”按钮的“命令”选项,以便在单击时调用类的内部 get_dir() 函数。但是,一旦我尝试运行该应用程序,就会调用 get_dir() 函数并提示我选择一个目录。任何想法为什么会发生这种情况,以及我可以做些什么来使其正常运行?

from Tkinter import *
import tkFont
from tkFileDialog import askdirectory

class App:

    def __init__(self, master):

        fontHead = tkFont.Font(family="Arial", size=10, weight=tkFont.BOLD)
        fontBold = tkFont.Font(family="Arial", size=8, weight=tkFont.BOLD)
        fontReg =  tkFont.Font(family="Arial", size=8)

        frameN = Frame(master)
        frameN.grid(row=0,padx=5,pady=5)

        frameXBH = Frame(frameN)
        frameXBH.grid(row=0,columnspan=5,padx=5)

        Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=20,background="#cccccc").grid(row=0)
        Label(frameXBH, text="Xbox 360",font=fontBold,width=9).grid(row=0,column=1)
        Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=440,background="#cccccc").grid(row=0,column=2,sticky="WE")

        Label(frameN, text="Destination Path:",font=fontReg).grid(row=1,sticky="W")
        xbPath = Entry(frameN,width=30,font=fontReg)
        xbPath.grid(row=1,column=1,sticky="W")
        xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))
        xbBrowse.grid(row=1,column=2,sticky="W")
        xbRel = Checkbutton(frameN,text="Release",font=fontReg)
        xbRel.grid(row=1,column=3,sticky="W")
        xbShip = Checkbutton(frameN,text="Ship",font=fontReg)
        xbShip.grid(row=1,column=4,sticky="W")

        Canvas(frameN,borderwidth=1,relief="groove",width=550,height=0).grid(row=2,columnspan=5,pady=10)

        # SAVE AND CANCEL

        btnSave = Button(frameN,text="Save",width=10)
        btnSave.grid(row=3,column=3,sticky="E")

        btnCancel = Button(frameN,text="Cancel",width=10)
        btnCancel.grid(row=3,column=4,sticky="W")

    def get_dir(self,box):
        tmp = askdirectory(mustexist=1,title="Please select a destination")
        tmp = tmp.replace("/","\\")
        box.delete(0,END)
        box.insert(0,tmp)

root = Tk()
root.resizable(0,0)

app = App(root)

root.mainloop()

【问题讨论】:

Why is Button parameter “command” executed when declared?的可能重复 @nbro 我认为您的副本倒退了,我在 2010 年问过这个问题,而您在 2011 年问过这个问题 -_- 我将这篇文章标记为另一个重复的原因是因为另一个实际上包含更多信息并且这个问题更简单.. 【参考方案1】:

将您的事件处理程序设为 lambda 函数,它会使用您想要的任何参数调用您的 get_dir()

xbBrowse = Button(frameN, text="Browse...", font=fontReg, command=lambda : self.get_dir(xbPath))

【讨论】:

你能通过添加 lambda 部分来解释这是做什么的吗?我在 Tkinter 文档中的最小应用程序中遇到了这个问题,我想在按下按钮时向窗口添加文本。我让 command=label.grid() 在它运行时添加了一个标签,并添加了 lamba 修复它。为什么没有 lambda 的命令会立即执行? lambda 关键字在做什么? 这里也一样 - 我尝试了 lambda,它也可以工作。它做了什么? 这个答案解释了更多:***.com/questions/8269096/…【参考方案2】:

在上面的代码中:

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))

您已经在调用该函数,您应该只是传递该函数:

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir)

【讨论】:

@Doktor J:你不需要传递对你的 xbPath 的引用,看看我的回答【参考方案3】:

您需要传递您的get_dir 方法的引用

所以改变

xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))

xbBrowse = Button(frameN,text="Browse...",font=fontReg, command=self.get_dir)

然后将您的 Entry 小部件设为实例变量,以便您可以在您的 get_dir 方法中访问它。

例如

self.xbPath = Entry(frameN,width=30,font=fontReg)

那么您的get_dir() 方法将如下所示:

def get_dir(self):
    tmp = askdirectory(mustexist=1,title="Please select a destination")
    tmp = tmp.replace("/","\\")

    self.xbPath.delete(0,END)
    self.xbPath.insert(0,tmp)

【讨论】:

我打算在表单上有多个浏览按钮/条目,所以我需要有多个按钮调用 get_dir() 并将其传递给适当的条目字段......你会怎么做? @Doktor J:传统的方法是为每个事件设置一个单独的处理程序,因此在您的情况下,每个浏览按钮都有一个单独的 get_dir() 方法,或者您可以实现您的浏览按钮 +条目小部件 +.. 作为复合小部件并让它自动执行您想要的所有事情,即获取显示它的路径过程等。然后它就像创建任意数量的复合小部件实例一样简单。

以上是关于Tkinter 按钮命令在运行程序时激活?的主要内容,如果未能解决你的问题,请参考以下文章

使用 tkinter 悬停时更改按钮颜色

基于选定的单选按钮在 Tkinter 中启动命令?

激活 Tkinter 顶层

调用类时所有函数都在运行(tkinter)[重复]

如何使用 Tkinter 按钮运行 Python 脚本?

Python & Tkinter -> 关于调用冻结程序的长时间运行函数