将dict [key]循环到gui界面,删除和替换

时间:2016-08-21 07:44:46

标签: python python-2.7 tkinter

所以我有Python 2.7的代码来计算字频率(欢迎任何优化)。

import Tkinter as tk

def let_freq():
    user_input = e.get()
    alphabet = {
        'a': 0,'b': 1,'c': 2,'d': 3,
        'e': 4,'f': 5,'g': 6,'h': 7,
        'i': 8,'j': 9,'k': 10,'l': 11,
        'm': 12,'n': 13,'o': 14,'p': 15,
        'q': 16,'r': 17,'s': 18,'t': 19,
        'u': 20,'v': 21,'w': 22,'x': 23,'y': 2,'z': 25}

    value_alphabet = {
        'a': 0,'b': 0,'c': 0,'d': 0,
        'e': 0,'f': 0,'g': 0,'h': 0,
        'i': 0,'j': 0,'k': 0,'l': 0,
        'm': 0,'n': 0,'o': 0,'p': 0,
        'q': 0,'r': 0,'s': 0,'t': 0,
        'u': 0,'v': 0,'w': 0,'x': 0,'y': 0,'z': 0}

    letters = []
    count = 0
    for character in user_input:
        letters.append(character)

    for item in letters:
        for key, val in alphabet.items():
            if key is item:
                value_alphabet[key] += 1

    for key in value_alphabet:
        if value_alphabet[key] > 0:
            count += value_alphabet[key]

    for key in sorted(value_alphabet):
        if value_alphabet[key] > 0:
            print value_alphabet[key], ',', key, '-', float(value_alphabet[key])/count*100, '%'


root = tk.Tk()
e = tk.Entry(root)
assert type(e)
e.grid(ipadx=5,ipady=5)
button = tk.Button(root, text='Letterfrequency',command=let_freq).grid(ipadx=5, ipady=5)
root.mainloop()

现在,问题是显示

print value_alphabet[key], ',', key, '-', float(value_alphabet[key])/count*100, '%'

在Tkinter标签或任何其他适当的Tkinter小部件中,我想知道如何在循环中主动编辑Label,如果user_input变量发生变化则删除它们,并且(这应该自然而然)显示user_inpute'部分之前e.get())中新条目的信息。

(即如果你输入'banana',你应该得到-50%,n-33.333333333%,b-16.666666666%......这是字频)

2 个答案:

答案 0 :(得分:1)

设置标签时,您可以为其设置tkinter.StringVar作为文本变量。然后,每当您更新变量时,Label都会自动更新:

from tkinter import *
from time import sleep

root = Tk()
labeltext = StringVar()
labeltext.set('hello')

label = Label(root, textvariable = labeltext)
label.pack()

for i in range(10):
    labeltext.set(str(i))
    root.update_idletasks()
    sleep(1) #slow it down so that the changes are visible

此代码将更新for循环内的标签。现在,您只需要labeltext.set(str(user_input)),您就会在标签上获得用户输入。

答案 1 :(得分:1)

在回答手头的问题之前,对你的功能做了一些调整。你正在做一些你并不真正需要的东西,并且可以减少这一点。

首先,您的value_alphabet只是重新实现的collections.Counter。请改用它。

from collections import Counter

...

    value_alphabet = Counter()

你也在做一些时髦的低级别的东西,A)在Python中是不必要的,B)即使有必要,也不是Python中最好的方法。我在谈论

letters = []

for character in user_input:
    letters.append(character)

这只是

letters = list(user_input)

但是因为你可以直接在字符串上迭代,所以你不需要letters AT ALL。去掉它。同样地,count只是len(user_input)。你所做的就是遍历每个字母并计算它们。扔了它。现在您的功能如下:

def let_freq():
    user_input = e.get()
    alphabet = {
        'a': 0,'b': 1,'c': 2,'d': 3,
        'e': 4,'f': 5,'g': 6,'h': 7,
        'i': 8,'j': 9,'k': 10,'l': 11,
        'm': 12,'n': 13,'o': 14,'p': 15,
        'q': 16,'r': 17,'s': 18,'t': 19,
        'u': 20,'v': 21,'w': 22,'x': 23,'y': 2,'z': 25}
    value_alphabet = Counter()

    for item in user_input:
        for key,val in alphabet.items():
            if key is item:
                value_alphabet[key] += 1

这个循环非常难看。你忽略了字典中最好的部分:O(1)查找!您不需要执行双循环。 if key is item由于其他原因是不好的,但我不会在这里讨论,因为身份与平等并不是真的在同一个鱼群中(并且它不会影响这里的功能。只要知道' somestring是somestring'并不总是True。)

   for ch in user_input:  # changed the loopvar here to sound better
       value_alphabet[ch] += alphabet[ch]
       # look it up directly.

如果您担心user_input包含无效字符,请使用dict.get来默认为零。

   for ch in user_input:
       value_alphabet += alphabet.get(ch, 0)
       # if ch isn't in alphabet, do value_alphabet += 0

甜!我们现在几乎整理好了。让我们继续。由于我们已经取消了您的count变量,因此我们可以跳过下一个for key in value_alphabet循环,因为它只填充count。最后一点,您可以通过执行以下操作来缩短代码:

for key,val in sorted(value_alphabet.items()):
    if val > 0:
        print val, ',', key, '-', float(val * 100 / len(user_input)), '%'

现在关于更改标签的问题?你正在寻找回调。你可能应该把它放到自己的类中,而不是让它在不知名的地方闲逛,但让我们谈谈将回调绑定到用户条目更改。最简单的方法是使用tk.StringVar及其trace方法。

root = tk.Tk()
e_stringvar = tk.StringVar()
e = tk.Entry(root, textvariable=e_stringvar)
e_stringvar.trace('w', some_func)

这会将e_stringvar与您的tk.Entry窗口小部件绑定在一起,将e的内容存储在e_stringvar中。此外,它将一些未知函数some_func绑定到e_stringvar,以便每次e_stringvar都有写入内容(例如e由于用户输入而发生更改),它会调用{{ 1}}。我们可以将some_func定义为:

some_func

我已经定义f = tk.Label(root) f.pack() e.pack() # whatever, pack everything def some_func(*args, **kwargs): text = e_stringvar.get() f.configure(text=text) # change the f label so it's displaying the same text as the entry 来接受参数,因为我老实说忘了some_func回调函数是否通过了触发它们的事件。我们没有使用它们,但如果你不允许它通过,你将获得ArgumentErrors。

我最近写了一些(Py3)代码,它使用这个概念来跟踪tk.StringVar.trace字段并使用它来过滤文本列表。相关代码位于bitbucket findppw.views.frames(FilterFrame类)和findppw.app(第38行实例化FilterFrame并命名其回调函数)