【问题标题】:Text Input in TkinterTkinter 中的文本输入
【发布时间】:2020-10-07 18:02:38
【问题描述】:

目标

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

代码

为此,我有以下代码:

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()

真正让我困惑的是:

  1. var 没有我输入的值,它有空字符串 ''
  2. a.string 变量具有我输入的值,我从 shell 中检查了它。

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

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

规格

操作系统:Linux Mint 14

Python IDLE 2.7

帮我解决这个问题。

【问题讨论】:

  • Mainloop 只不过是一个看起来大致类似于while the_main_window_exists(): get_the_next_event(); process_the_event() 的无限循环。它没有什么特别神秘的地方。

标签: python tkinter


【解决方案1】:

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

您可以依靠 tkSimpleDialog 家人获得您的意见:

import Tkinter
import tkSimpleDialog

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

如果您想按照自己的方式行事,可以从“确定”按钮回调(在您的情况下为gettext)执行打印。您还可以在按下“ok”时生成一个虚拟事件并在主程序中绑定到该事件 (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/virtual-events.html)

【讨论】:

  • 是的。我发现这是最简单的做事方式!
【解决方案2】:

你的代码流程是这样的:

  • 主作用域调用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

【讨论】:

  • SIr:如果我在执行mainloop() 之后只打印值会好吗?那是对的吗?我检查了它,它确实有效。
【解决方案3】:

问题是您的测试例程在显示对话框之前已经打印出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 等中找到)来了解它是如何完成的。

【讨论】:

  • "即使在点击确定后你也必须关闭框架"。这是因为“okay”按钮的回调只会破坏框架。根窗口仍未被破坏,所以mainloop 将继续循环。如果你在回调中销毁根而不是仅仅销毁帧,那么mainloop 将结束。
  • @Kevin 是的,我是这么想的,但我不确定从另一个 Tk 框架中创建此输入对话框时会发生什么。
  • 不,先生。我不打算关闭窗口,因为我必须在我正在构建的应用程序中打印一些其他内容。
【解决方案4】:

这是一个快速的 sn-p:

import tkinter
from tkinter import simpledialog

root = tkinter.Tk()
# withdraw() will make the parent window disappear.
root.withdraw()
# shows a dialogue with a string input field
youtube_url = simpledialog.askstring('YouTube URL', 'Enter the youtube URL of the video', parent=root)

if str(youtube_url).startswith('http'):
    pass
else:
    pass

【讨论】:

  • 最好解释一下,你在做什么,这样人们会发现它很有用,即使它是 cmets 的形式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2014-03-20
  • 2021-03-23
  • 1970-01-01
  • 2017-04-23
  • 2019-01-15
相关资源
最近更新 更多