【问题标题】:python: Taking an Tkinter entry valuepython:获取 Tkinter 条目值
【发布时间】:2013-01-02 21:14:28
【问题描述】:

我一直在尝试获取一个条目值(代码中的 S1)以将其自身设置为一个值(_attributes 字典中的 STR),但我无法让它工作。我想把它做成一个最终的toploop,但我会一步一步来,因为我一般都是编程新手。我是否以正确的方式进行此操作,还是应该只使用一个按钮,当按下该按钮时,会在当时查找条目值并与之一起使用?我已经阅读了我在网上为 Tkinter 找到的几个教程和课程,但似乎距离让任何事情都按照我期望的方式工作还有很长的路要走。

#! usr/bin/python27
from Tkinter import *

class Character:

    def __init__(self, **kvargs):
        self._attributes = kvargs

    def set_attributes(self, key, value):
        self._attributes[key] = value
        return

    def get_attributes(self, key):
        return self._attributes.get(key, None)


def attrInput(stat, x, y):
   """Creates a label for entry box"""
   L = Label(B,
             width = 5,
             relief = RIDGE,
             anchor = E,
             text = stat).grid(row = x,
                             column = y)

B = ""
def main():

    Person = Character()

    B = Tk()

    S1 = Entry(B, width = 3)
    S1.grid(row = 0, column = 1)
    S1.bind("<Key>", Person.set_attributes('STR', S1.get()) )
    attrInput("Str: ", 0, 0)

    Button(B, text='Quit', command=B.destroy).grid(row=3, column=0, sticky=W, pady=4)

    B.mainloop()

    print Person.__dict__

if __name__ == '__main__': main()

新代码(似乎正在运行,至少我得到了我想要的东西)。我将不得不稍微修改它以使其成为顶部循环,但这是基础

class Character:

    def __init__(self, **kvargs):
        self._attribute = kvargs

    def set_attribute(self, key, value):
        self._attribute[key] = value
        return

    def get_attribute(self, key):
        return self._attribute.get(key, None)


class attrAsk:

    def __init__(self, master, Char, attrName, Row, Column):
        self.Char = Char
        self.attrName = attrName
        attrInput(attrName+":", Row, Column)
        self.e = Entry(master, width = 3)
        self.e.grid(row = Row, column = Column+1)
        self.e.bind("<KeyRelease>", self.set_attr)

    def set_attr(self, event):
        self.Char.set_attribute(self.attrName, self.e.get())


def attrInput(stat, x, y):
   """Creates a label for entry box"""
   L = Label(box,
             width = 5,
             relief = RIDGE,
             anchor = E,
             text = stat).grid(row = x,
                               column = y)

Person= Character()


box = Tk()

STRENT = attrAsk(box, Person, "STR", 0, 0)
DEXENT = attrAsk(box, Person, "DEX", 1, 0)
CONENT = attrAsk(box, Person, "CON", 2, 0)
INTENT = attrAsk(box, Person, "INT", 3, 0)
WISENT = attrAsk(box, Person, "WIS", 4, 0)
CHAENT = attrAsk(box, Person, "CHA", 5, 0)

Button(box,
       text='Continue',
       command=box.destroy).grid(columnspan = 2,
                                                       row=8,
                                                       column=0,
                                                       sticky=W,
                                                       pady=4)

box.mainloop()

print Person.__dict__

【问题讨论】:

  • 目前工作方式的具体问题是什么?

标签: python tkinter binding tkinter-entry


【解决方案1】:

换行:

S1.bind("<Key>", Person.set_attributes('STR', S1.get()) )

类似于:

def key_pressed(event):
    Person.set_attributes('STR', S1.get())
S1.bind("<KeyRelease>", key_pressed)

原代码不起作用有两个原因:

  1. bind 将一个函数作为它的第二个参数——然后在事件发生时调用该函数。但是,当您使用它时,Person.set_attributes('STR', S1.get()) 表达式只会发生立即。您需要将该表达式放入一个函数中,以便它仅在按下键时发生。
  2. &lt;Key&gt; 表示事件在第一次按下键时发生,但您希望它在键释放时发生(因此添加了新字符)。因此,您想使用&lt;KeyRelease&gt;

另一个注意事项:将所有功能(尤其是回调方法)组织到一个类中是个好主意。例如:

class Window(object):
    def __init__(self):
        self.person = Character()

        self.B = Tk()

        self.S1 = Entry(B, width = 3)
        self.S1.grid(row = 0, column = 1)

        self.S1.bind("<KeyRelease>", self.key_pressed)
        attrInput("Str: ", 0, 0)

        self.button = Button(B, text='Quit', command=self.B.destroy).grid(row=3, column=0, sticky=W, pady=4)

        self.B.mainloop()

        print self.person.__dict__

    def key_pressed(self, event):
        self.person.set_attributes('STR', self.S1.get())


def main():
    w = Window()


if __name__ == '__main__': main()

这种组织的好处可能不会立即显现出来,但是一旦您拥有大量回调方法并跟踪大量小部件,它就会变得非常有用。

响应您的评论,您可以在 for 循环中创建 EntryLabel 对象,每个对象都在自己的行中。然后key_pressed 方法可以从传递给它的event 对象中学习字段和输入文本,如下所示(尝试一下):

class Window(object):
    def __init__(self):
        self.person = Character()

        self.B = Tk()

        self.fields = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]

        self.inputs = {}
        for i, f in enumerate(self.fields):
            self.inputs[f] = Entry(B, width = 3)
            self.inputs[f].grid(row=i, column=1)
            self.inputs[f].bind("<KeyRelease>", self.key_pressed)
            attrInput(f + ":", i, 0)

        self.button = Button(B, text='Quit', command=self.B.destroy).grid(row=7, column=0, sticky=W, pady=4)

        self.B.mainloop()

        print self.person.__dict__

    def key_pressed(self, event):
        field = self.fields[int(event.widget.grid_info()["row"])]
        self.person.set_attributes(field, event.widget.get())

【讨论】:

  • @Mr.Robinson 我想为一系列输入执行此操作。有什么方法可以让我编码为可重用的,还是我只是坚持为每个输入创建一个函数?
  • @DJ80 您可能不需要每个输入一个函数,但您需要更好地定义您的问题,以便正确回答。
  • 我希望有一系列 6 个条目,例如 S1,它们将值分配到 Person _attributes 字典中,以及其他形式的其他几种类型的输入也一样。我希望通过一系列小部件(一些条目、一些 Spinbox、一些列表)来做到这一点。是否有一个我可以编写的函数允许我在执行 key_pressed 时接受一个参数,以便我可以将适当的值附加到字典中的正确键?
  • @DJ80:疯狂猜测:是STR、CON、DEX、INT、WIS、CHA吗?
  • @DavidRobinson,是的,你发现了我的秘密;) 今天早上,我通过创建一个我可以用于这些条目以及更多内容的类,成功地完成了一些工作。我将编辑我的原始帖子以添加新课程。如果您可以查看它以确保我不会在节目的后期阶段自欺欺人,我将不胜感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-06
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多