通过Tk小部件/窗口路径名访问小部件

时间:2014-12-03 14:26:26

标签: python python-3.x tkinter widget tk

我正在使用validatecommand来动态地观察和验证条目小部件的输入。

validatecommand的标准用法可防止将无效字符输入到观察到的条目窗口小部件中。这不是我喜欢的行为,所以我使用validatecommand将条目小部件的字符串传递给另一个函数,并且return True在任何情况下都是如此。 floatstr_to_float使用名为preg的正则表达式验证字符串。

如果正则表达式匹配输入有效,则一切正常,因此执行print('approved')。但是,如果用户输入了无效输入,则正则表达式不匹配,执行print('not approved')并且相应的条目小部件应填充为红色(颜色的更改尚未正确实现)。

到目前为止,我所做的是使用<widget>.config(bg=<background>)更改第一个条目窗口小部件的背景,以检查我能够通过索引所有创建的条目窗口小部件的列表来访问每个窗口小部件。

validatecommand可以将几个arguments传递给已执行的函数(例如imput / text string和widget / window pathname)。因此,获得对无效小部件的引用通常不是问题。但是,validatecommand传递的路径名似乎不是python可访问的。如何通过在包含(in)有效输入的小部件上执行<widget>.config(bg=<background>)来从此路径名获取引用(例如,唯一变量名称)来更改背景?

- MWE -

#!/usr/bin/env python3
# -*- coding: <utf-8> -*-

# code adapted from:
# http://stackoverflow.com/questions/4140437/python-tkinter-interactively-validating-entry-widget-content

import tkinter as tk
import re

class MyApp():
    def __init__(self):
        self.root = tk.Tk()
        self.parameternames = [
            ('a', 'U'), ('b', 'U'), ('c', 'U'), ('d', 'U'), ('e', 'U'),
            ('f', 'U'), ('g', 'U'), ('h', 'U'), ('i', 'U'), ('j', 'U'),
            ('k', 'U'), ('l', 'U'), ('m', 'U'), ('n', 'U'), ('o', 'U'),
            ('p', 'U'), ('q', 'U'), ('r', 'U'), ('s', 'U'), ('t', 'U')]
        self.vcmd = (self.root.register(self.OnValidate), '%P', '%W')
        self.create_widgets()

    def create_widgets(self):
        self.entries = []
        for i in enumerate(self.parameternames):
            entry = tk.Entry(self.root, validate="all", validatecommand=self.vcmd)
            self.default_bg = entry.cget("bg")
            entry.pack()
            self.entries.append(entry)
        self.root.mainloop()

    def OnValidate(self, P, W):
        # %P = value of the entry if the edit is allowed
        # %W = the tk name of the widget (pathname)
        print("OnValidate:")
        print("P='%s'" % P )
        print("W='%s'" % W )
        self.floatstr_to_float(P, W)
        # return True to display inserted character, validation is done by a re in 'floatstr_to_float()'
        return True

    def floatstr_to_float(self, fs, W):
        preg = re.compile('^\s*(?P<int>\d*)\s*[\.,]?\s*(?P<dec>\d*)\s*$')
        m = preg.match(fs)
        if m:
            print('approved')
            intprt=m.group('int')
            frcprt=m.group('dec')
            f = 0. if (intprt == '' and frcprt == '') else float('%s.%s' %(intprt, frcprt)) # not needed yet
            # currently:    just changing the color of the first entry widget (proof of concept)
            # aim:          pass unique name of edited entry widget to self.change_bg() for changing bg of
            #               appropriate entry widget
            self.change_bg(self.entries[0], 1)
        else:
            print('not approved')
            # see comment in if-statement above
            self.change_bg(self.entries[0], 0)

    def change_bg(self, name, approved):
        if approved == 1:
            name.config(bg=self.default_bg)
        else:
            name.config(bg='#d9534f')

app=MyApp()

1 个答案:

答案 0 :(得分:3)

您可以使用nametowidget的{​​{1}}方法。这将根据其名称查找窗口小部件。所以使用:

Tk