Python 当我从lambda调用tkSimpleDialog.askstring时,为什么Tkinter挂起?

Python 当我从lambda调用tkSimpleDialog.askstring时,为什么Tkinter挂起?,python,lambda,tkinter,Python,Lambda,Tkinter,我正在开发一个GUI应用程序来模拟一篇文章。除此之外,用户可以创建一个新主题,然后用注释填充该主题。目前,我有两种创建新主题的方法:通过菜单中的下拉选项(菜单命令)和主屏幕上的按钮(按钮命令)。按钮以文本“新主题”开始使用。当用户按下按钮时,程序生成一个新主题,要求用户使用tkSimpleDialog.askstring命名该主题,然后将按钮文本设置为该主题的名称和该主题中的注释数。然后,按钮的命令将更改为向该主题添加注释 在开发程序时,我首先验证了菜单命令是否有效。它成功地调用了askstri

我正在开发一个GUI应用程序来模拟一篇文章。除此之外,用户可以创建一个新主题,然后用注释填充该主题。目前,我有两种创建新主题的方法:通过菜单中的下拉选项(菜单命令)和主屏幕上的按钮(按钮命令)。按钮以文本“新主题”开始使用。当用户按下按钮时,程序生成一个新主题,要求用户使用
tkSimpleDialog.askstring
命名该主题,然后将按钮文本设置为该主题的名称和该主题中的注释数。然后,按钮的命令将更改为向该主题添加注释

在开发程序时,我首先验证了菜单命令是否有效。它成功地调用了
askstring
,创建了一个新的弹出窗口,以我想要的方式处理输入。但是,我一添加按钮命令,对
askstring
的调用就失败了,即使是通过菜单命令调用。应该有askstring对话框的窗口变白,程序挂起。如果我注释掉按钮命令,它会再次工作。如果我注释掉菜单命令,它将挂起

下面是我将命令添加到菜单的代码:

        TopicBtn.menu.add_command(label="New Topic", underline=0,
                                  command=self.newTopic)
以下是newTopic()的代码:

以下是newTopicButton()的代码:


请注意,从
button.bind(“,(lambda e,s=self:s.newLabel())
切换到
button=button(frame,text=“askstring”,command=(lambda s=self:s.newLabel())
修复了错误(但没有给我一个被按下的按钮的参考)。我认为问题与将事件捕获为lambda的输入之一有关。

我找到了一个解决方法。从最简单的示例测试来看,问题似乎来自单独调用bind,从而接受事件作为lambda的输入。如果有人能解释为什么会发生这种情况,我会接受他们的答案,而不是我的答案,但我现在会接受这个答案

解决方法不是使用单独的绑定函数,而是创建一个按钮数组,然后将数组中的正确条目作为参数传递给lambda函数(不能传递按钮本身,因为它是在具有lambda函数的行中创建的)

代码如下:

from Tkinter import *
import tkSimpleDialog

class Min():

    def __init__(self, master=None):
        root = master
        frame = Frame(root)
        frame.pack()

        buttons = [None] * 2
        for i in range (2):
            buttons[i] = Button(frame, text="askstring",
                            command=(lambda s=self, var=i: s.newLabel(buttons[var])))
            buttons[i].grid()

    def newLabel(self, button):
        label = tkSimpleDialog.askstring("New Label", "What should the label be?")
        button.config(text=label)
        print label

root = Tk()
m = Min(root)
root.mainloop()

您在这里遇到的问题是由于您正在使用的对话框中调用了
wait\u window
(您自己从来没有调用过它,但实现该对话框的代码却调用了它)。例如,以下代码在(可能)两次单击按钮后复制了该问题:

import Tkinter

def test(event=None):
    tl = Tkinter.Toplevel()
    tl.wait_window(tl)

root = Tkinter.Tk()
btn = Tkinter.Button(text=u'hi')
btn.bind('<Button-1>', test)
btn.pack(padx=10, pady=10)
root.mainloop()

从所包含的来源很难判断。尝试用(新的)常规方法替换
lambda
express,看看情况是否发生了变化。解决这一问题的最佳方法是首先构造一个简化的示例,给出与您现在遇到的相同的问题。到那时,你可能会发现你的错误,否则就用它更新你的问题。谢谢,我想Tkinter机器中发生了一些我不理解的事情。与阵列相比,我更喜欢两步过程。我假设
btn['command']=myCommand
等同于
btn.config(command=myCommand)
,对吗?
for col in range(self.TOPICS_PER_ROW):
     button = Button(self.topicFrame, text="New Topic")
     button.bind("<Button-1>", (lambda e, s=self: s.newTopic(e.widget)))
     button.grid(row=0, column=col, sticky=NSEW, padx=10, pady=10)
from Tkinter import *
import tkSimpleDialog

class Min():

    def __init__(self, master=None):
        root = master
        frame = Frame(root)
        frame.pack()

        button = Button(frame, text="askstring")
        button.bind("<Button-1>", (lambda e, s=self: s.newLabel()))
        button.grid()

    def newLabel(self):
        label = tkSimpleDialog.askstring("New Label", "What should the label be?")
        print label

root = Tk()
m = Min(root)
root.mainloop()
from Tkinter import *
import tkSimpleDialog

class Min():

    def __init__(self, master=None):
        root = master
        frame = Frame(root)
        frame.pack()

        buttons = [None] * 2
        for i in range (2):
            buttons[i] = Button(frame, text="askstring",
                            command=(lambda s=self, var=i: s.newLabel(buttons[var])))
            buttons[i].grid()

    def newLabel(self, button):
        label = tkSimpleDialog.askstring("New Label", "What should the label be?")
        button.config(text=label)
        print label

root = Tk()
m = Min(root)
root.mainloop()
import Tkinter

def test(event=None):
    tl = Tkinter.Toplevel()
    tl.wait_window(tl)

root = Tkinter.Tk()
btn = Tkinter.Button(text=u'hi')
btn.bind('<Button-1>', test)
btn.pack(padx=10, pady=10)
root.mainloop()
for i in range(X):
    btn = Tkinter.Button(text=u'%d' % i)
    btn['command'] = lambda button=btn: some_callback(button)