首页 文章

Tkinter中的文本输入

提问于
浏览
1

Goal

我正在尝试编写一个基本文件,我可以在所有其他程序中导入,这些程序将具有一个简单的功能,将从用户输入然后返回它 .

Code

为此,我有以下代码:

class takeInput(object):

    def __init__(self,requestMessage,parent):

        self.string = ''
        self.frame = Frame(parent)
        self.frame.pack()        
        self.acceptInput(requestMessage)

    def acceptInput(self,requestMessage):

        r = self.frame

        k = Label(r,text=requestMessage)
        k.pack(side='left')
        self.e = Entry(r,text='Name')
        self.e.pack(side='left')
        self.e.focus_set()
        b = Button(r,text='okay',command=self.gettext)
        b.pack(side='right')

    def gettext(self):
        self.string = self.e.get()
        self.frame.destroy()
        print self.string

    def getString(self):
        return self.string

def getText(requestMessage,parent):
    global a
    a = takeInput(requestMessage,parent)
    return a.getString()

我还添加了一些脚本级代码,以便测试:

root = Tk()

getText('enter your name',root)

var = a.getString()

print var

root.mainloop()

真令我困惑的是:

  • var 没有我输入的值有空字符串 ''

  • a.string 变量具有我输入的值,我从shell中检查了它 .

Also 当我尝试将从 a.getString() 返回的字符串分配给shell中的 var 时,它就起作用了 .

note 我是Tkinter编程的新手,并不完全理解 mainloop() 的工作原理 . 所以也许这就是问题所在 . 但我不确定 .

Specs

操作系统:Linux Mint 14

Python IDLE 2.7

Please 帮我解决这个问题 .

3 回答

  • 1

    您的代码流程如下:

    • 主要范围调用 getText .

    • getText 创建 takeInput 对象 a .

    • takeInput 对象初始化自己,创建标签和按钮等 .

    • getText 返回 a.getString() ,返回 self.string ,仍然有其默认值,即空字符串 .

    • 主范围打印 var ,这是空的 .

    到目前为止,所有这一切都发生在几纳秒的范围内 . 用户还没有看到窗口 .

    然后主范围调用 root.mainloop() ,最终使用户有机会与窗口进行交互 . 但为时已晚 . var 已经打印过 .

    如果您希望 getText 在用户提交文本之前不返回,那么 mainloop 必须在 getText 内发生,而不是在它之后 .

    from Tkinter import *
    
    class takeInput(object):
    
        def __init__(self,requestMessage):
            self.root = Tk()
            self.string = ''
            self.frame = Frame(self.root)
            self.frame.pack()        
            self.acceptInput(requestMessage)
    
        def acceptInput(self,requestMessage):
            r = self.frame
    
            k = Label(r,text=requestMessage)
            k.pack(side='left')
            self.e = Entry(r,text='Name')
            self.e.pack(side='left')
            self.e.focus_set()
            b = Button(r,text='okay',command=self.gettext)
            b.pack(side='right')
    
        def gettext(self):
            self.string = self.e.get()
            self.root.destroy()
    
        def getString(self):
            return self.string
    
        def waitForInput(self):
            self.root.mainloop()
    
    def getText(requestMessage):
        msgBox = takeInput(requestMessage)
        #loop until the user makes a decision and the window is destroyed
        msgBox.waitForInput()
        return msgBox.getString()
    
    var = getText('enter your name')
    print "Var:", var
    
  • 10

    正如其他答案所述,您在进入主循环之前打印 var ,也就是说,在您的窗口实际运行之前,并且您的程序正在等待用户输入 .

    您可以依靠 tkSimpleDialog 系列来获取您的输入:

    import Tkinter
    import tkSimpleDialog
    
    root = Tkinter.Tk()
    var = tkSimpleDialog.askstring("Name prompt", "enter your name")
    print var
    

    如果您想追求自己的方式,可以通过"ok"按钮回调(在您的情况下为 gettext )执行打印 . 您也可以在按下"ok"时生成虚拟事件并绑定到主程序中的此事件(http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/virtual-events.html

  • 7

    问题是您的测试例程在显示对话框之前已经打印出 var 的值,更不用说输入文本了 . (您可以通过在测试代码中添加一些 print 语句来轻松验证这一点 . )这是因为对 mainloop() 的调用已经到了最后 . 相反,您应该在创建帧之后调用 mainloop ,但在读取并返回输入之前,例如,它可能会转到你的 getText 方法:

    def getText(requestMessage,parent):
        a = takeInput(requestMessage,parent)
        parent.mainloop()
        return a.getString()
    

    这仍然不能很好地工作,因为你必须关闭对话框(单击 [x] -按钮),即使单击'okay',我不知道如何解决这个问题 .

    但请注意,已有一个模块, tkSimpleDialog ,提供了 askstring(title, prompt) 等方法,只显示这样的输入对话框 . 所以你可以使用它们,或者查看源代码(在 /usr/lib/python2.7/lib-tk 中找到),以了解它是如何完成的 .

相关问题