Tkinter中的文本输入
目标
我想写一个简单的文件,这样我就可以在其他程序中导入它。这个文件里会有一个简单的功能,可以接收用户输入,然后返回这个输入。
代码
为此,我写了以下代码:
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
这个变量有我输入的值,我在命令行中检查过了。
另外 当我尝试把 a.getString()
返回的字符串赋值给 var
时,这在命令行中是可以工作的。
注意 我是刚开始学习 Tkinter 编程,对 mainloop()
的工作原理还不太了解。所以可能问题出在这里,但我不太确定。
规格
操作系统:Linux Mint 14
Python IDLE 2.7
请 帮我解决这个问题。
4 个回答
问题在于,你的测试代码在对话框显示之前就已经打印出了var
的值,更不用说输入文本了。(你可以通过在测试代码中添加一些print
语句来验证这一点。)这是因为mainloop()
的调用是在最后的。相反,你应该在创建窗口后,但在读取和返回输入之前调用mainloop
,比如可以放在你的getText
方法里:
def getText(requestMessage,parent):
a = takeInput(requestMessage,parent)
parent.mainloop()
return a.getString()
不过,这样做还是不太好,因为即使点击了“确定”,你还得关闭对话框(点击[x]
按钮),我不太确定该怎么解决这个问题。
不过,要注意的是,实际上已经有一个模块可以做到这一点,叫做tkSimpleDialog
,它提供了像askstring(title, prompt)
这样的函数,可以显示输入对话框。所以你可以使用这些函数,或者查看源代码(在/usr/lib/python2.7/lib-tk
等地方找到)来了解它是怎么实现的。
正如其他回答所说,你在进入主循环之前打印了var
,也就是说在你的窗口实际上还没有运行的时候,你的程序就在等待用户输入了。
你可以使用tkSimpleDialog
这个家族来获取用户输入:
import Tkinter
import tkSimpleDialog
root = Tkinter.Tk()
var = tkSimpleDialog.askstring("Name prompt", "enter your name")
print var
如果你想继续你自己的方式,可以在“确定”按钮的回调函数中进行打印(在你的情况下是gettext
)。你也可以在按下“确定”时生成一个虚拟事件,并在你的主程序中绑定这个事件(http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/virtual-events.html)
你的代码执行流程是这样的:
- 主程序首先调用了
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