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

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

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

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

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

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

validatecommand可以通过几个arguments执行的函数(例如输入/文本字符串和小部件/窗口路径名)。因此,获取对无效小部件的引用通常不是问题。但是,validatecommand 传递的路径名似乎不是 python 可访问的。如何从此路径名获取引用(例如唯一变量名)以通过执行 <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()

最佳答案

您可以使用Tknametowidget 方法。这会根据其名称找到小部件。所以使用:

self.change_bg(self.root.nametowidget(W), 1)

关于python - 通过 Tk 小部件/窗口路径名访问小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27274172/

相关文章:

python - 如何使用 Django 表单创建过滤下拉列表?

python - 为什么要使用 is_safe?

python - 从十六进制转换为 base64

python-3.x - 无法使用 pypy 安装 scipy(g++ 构建错误)

python - 如何在 PyQt5 应用程序中更改 Matplotlib NavigationToolbar 的默认文件名?

python - 类型错误 : super() argument 1 must be type, 不是 classobj

python - 如何以二进制表示模式打印 numpy 数组

python - 获取组内的最大值,但不仅仅是第一个(ex æquo 也是如此)

python - 如何使用 Python 将多个标签变量转换为 tkinter 中的字典?

python - Tkinter 包布局 : Elastic band analogy