使用tkinter缩放窗口小部件数据列出理解

时间:2012-02-22 17:11:37

标签: python tkinter list-comprehension tkinter-scale

我正在尝试创建一个python 2.7 tkinter模块,该模块使用缩放窗口小部件数据来影响列表理解,该列表理解在概率特征被表示为列表列表的动物之间进行选择。模块在点击“提交”并激活相关命令后按排序降序排序并显示三只动物。

在这个例子中,点击“提交”后所有三只动物都达到了33%,因为它们共享相同的概率数据。动物仅在列表列表的第2列中的比例小部件数据之间不同,其中每个都是水生的,陆地的或两者。

from Tkinter import BOTH, BOTTOM, Button, E, END, Entry, FLAT, Frame, Grid, HORIZONTAL, Label, LEFT, N, NO, Pack, RAISED, RIGHT, S, Scale, Text, Tk, TOP, W, YES

from operator import mul

root = Tk()
root.title('Example')

class Environment:
    def __init__(self, parent):

        # layout
        self.myParent = parent

        self.main_frame = Frame(parent, background="light blue")
        self.main_frame.pack(expand=YES, fill=BOTH)

        self.main_left_frame = Frame(self.main_frame, background="light blue")
        self.main_left_frame.pack(side=LEFT, expand=YES, fill=BOTH)

        self.main_right_frame = Frame(self.main_frame, background="light blue")
        self.main_right_frame.pack(side=RIGHT, expand=YES, fill=BOTH)

        self.water = Scale(self.main_right_frame, from_=0.01, to=1.00, orient=HORIZONTAL, bd=0, label="Aquatic",
        background="white", troughcolor="cyan", length=50, width=10, sliderlength=10, resolution=0.01)
        self.water.pack()
        self.water.set(1.00)

        self.soil = Scale(self.main_right_frame, from_=0.01, to=1.00, orient=HORIZONTAL, bd=0, label="Terrestrial",
        background="white", troughcolor="saddle brown", length=50, width=10, sliderlength=10, resolution=0.01)
        self.soil.pack()
        self.soil.set(1.00)

        self.id_frame = Frame(self.main_left_frame, background="white")
        self.id_frame.pack(side=BOTTOM)

        # submit button
        self.submitbutton = Button(self.main_left_frame,text="Submit", background="black", foreground="white",
        width=6, padx="2m", pady="1m")
        self.submitbutton.pack(side=TOP)
        self.submitbutton.bind("<Button-1>", self.submitbuttonclick)
        self.submitbutton.bind("<Return>", self.submitbuttonclick)

        #Animal Matrix
        self.animal = [
        ('Odocoileous virginiana','White-tailed Deer',self.soil.get,0.99,0.01,0.99),
        ('Anguilla anguilla','American Eel',self.water.get,0.99,0.01,0.99),
        ('Trachemys scripta','Slider',lambda:self.soil.get()*self.water.get(),0.99,0.01,0.99)]

    def submitbuttonclick(self, event):
        self.id_frame.destroy()
        self.id_frame = Frame(self.main_left_frame, background="white")
        self.id_frame.pack(side=BOTTOM)

        A=self.animal

        #equation
        sigma = float(sum(reduce(mul,item[3:]) for item in A))
        B = [(item[0], "%.2f" % (item[2]()*reduce(mul, item[3:])/sigma)) for item in A]
        C = sorted(B, key=lambda item: item[1], reverse=True)  

        Label(self.id_frame, text = C[0], background = "white").pack(side=TOP, anchor = W)
        Label(self.id_frame, text = C[1], background = "white").pack(side=TOP, anchor = W)
        Label(self.id_frame, text = C[2], background = "white").pack(side=TOP, anchor = W)

environment = Environment(root)       
root.mainloop()

感谢许多改进,这段代码有效!

3 个答案:

答案 0 :(得分:0)

A[2][i]/sigma*A[2][i] 这一点试图索引浮点数。 这应该是:A[i]/sigma*A[i]而不是吗?

我确实假设A中的值都是浮点数。

答案 1 :(得分:0)

我注意到的第一件事是你将A定义为空字典,然后使用self.animal覆盖该空字典,这是一个列表。

    A={}
    A=self.animal

所以我不确定你在这里做什么意思。然后在您对B的定义中将其切片:

    B = [(A[0], "%.2f" % (reduce(mul,A[3:])*A[2][i]/sigma*A[2][i])) for A in A]

这与[{1}}的 定义不一致,因为您无法对dict进行切片,但您选择的起始索引为A,且最高3中的索引为self.animal。混乱!但仔细观察,很明显,问题在于您正在重用2作为索引变量。你真的不应该这样做;它使这段代码难以置信令人困惑。

它也可能导致错误。请考虑以下代码:

A

如您所见,列表推导使>>> a = range(10) >>> [a for a in a] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a 9 引用先前称为a的序列中的最后一个值。这不会发生在您的代码中,因为您使用了生成器表达式。但它仍然难以阅读和混淆。我强烈建议改为:

a

更新:好的,进行了这些更改后,您仍然需要 sigma = float(sum(reduce(mul,item[3:]) for item in A)) B = [(item[0], "%.2f" % (reduce(mul,item[3:])/sigma)) for item in A] 来自比例尺的数据。在您对get的定义中,您使用self.animal,如下所示:

self.soil.get()

这会将('Odocoileous virginiana','White-tailed Deer',self.soil.get(),0.99,0.01,0.99) 的返回值置于元组中。但那个价值是固定的 - 它永远不会改变。您必须每次明确地调用{/ 1}} 您想要更新的值。此外,您的列表推导不会访问返回的值。你像这样切片:

self.soil.get()

请记住,列表和元组中的索引以self.soil.get()开头 - 所以在上面的元组>>> l = ('Odocoileous virginiana','White-tailed Deer', ... self.soil.get(), 0.99, 0.01, 0.99) >>> l[3:] (0.98999999999999999, 0.01, 0.98999999999999999) 0中。因此,如果你想要除了前两件事之外的所有东西,你必须从索引2切片:

l

但是这仍然无法解决根本问题,即您必须调用l[0] == 'Odocoileous virginiana'来获取更新的数据。您可以这样做的一种方法是每次点击提交按钮时重新创建>>> l[2:] (0.55000000000000004, 0.98999999999999999, 0.01, 0.98999999999999999) 。这将是浪费,但它会起作用。一种不那么浪费(但仍然很尴尬)的方法是将函数本身保存在元组中,而不是函数的结果。你这样做是这样的:

self.soil.get()

请注意self.animal之后缺少>>> l = ('Odocoileous virginiana','White-tailed Deer', ... self.soil.get, 0.99, 0.01, 0.99) 。现在,元组不包含浮点值,而是包含返回浮点值的函数。您必须调用它来获取值,但每次都返回完全更新的值。要组合功能,您可以使用()

self.soil.get

现在,您可以致电lambda获取值:

>>> l = ('Odocoileous virginiana','White-tailed Deer',
...      lambda: self.soil.get() * self.water.get(), 0.99, 0.01, 0.99)

所以要把它们放在一起,你必须更多地分解列表理解以明确地调用l[2],但是一旦你完成了这个,这应该可行。这不是一个理想的设置,但我担心我不得不创建一个改进的架构作为读者的练习。

答案 2 :(得分:0)

for A in A部分对我来说似乎有点狡猾。它可能在语法上是正确的,但是对于这些集合中的集合和元素使用不同的名称通常更清楚。

使用for isolates in A: i = A.index(isolates)可以提高for i, isolates in enumerate(A)效率,因为当{A}很大时,A.index(isolates)可能会花费很长时间。

我知道,这不是你问题的答案,但我希望它仍然有用。

为了便于调试(并实际帮助您),请重写:

[(A[0], "%.2f" % (reduce(mul,A[3:])*A[2][i]/sigma*A[2][i])) for A in A]

进入更具可读性的东西。如果将它拆分为具有多行的东西,您实际上可以使用调试器,并轻松查看哪个变量是“浮动”以及它被索引的位置。