Tkinter事件小部件

时间:2015-10-05 20:32:47

标签: python user-interface tkinter

我目前正在一个类中使用Tkinter制作GUI。我希望GUI根据之前的选择向用户询问各种输入。另外,我会注意到我对python相对较新,而且肯定是Tkinter。但是,我之前在MATLAB中制作过GUI。

所以,我想做的是以下内容:

  1. 询问用户要处理的速度,用逗号分隔。然后,用户将输入如下速度:[90,100,102p5]。
    • 要从条目中获取输入,您必须按Enter键,它将调用一个函数来获取速度字符串。然后我接受输入的字符串并根据逗号将其分开以形成列表。
  2. 然后,一旦输入速度,我想更新GUI并显示每个速度的输入部分,以便以该特定速度输入各种压力,用逗号分隔。压力将为[100kpa,200kpa,300kpa,400kpa]。
    • 要获得为每个压力输入的值,您必须按照之前的每个输入框中的Enter键。我再次将字符串形成压力列表。
  3. 我的方法有效,但我不认为这是最佳做法。这是链接,用于查看输入各种速度时GUI的外观,如步骤1中所述:GUI Image

    最终,在此GUI结束时,我想要一个速度列表,并为每个速度列出压力列表。然后,我将获取这些列表并将它们提供给另一个函数来运行我之前创建的程序。

    需要注意的一点是,我不知道用户想要处理多少速度。我也不知道每种速度会输入多少压力。

    所以,这些是我的问题: 这会是用Tkinter处理事件的“pythonic”方式吗?我没有在网上找到任何关于如何根据前一个完成(通过按Enter键)显示新小部件的内容。

    我也不是100%确定在不同方法之间传递变量的最佳方法是使变量成为self的属性。例如,我如何传递“速度”变量和字典“bp”。我应该使用全局变量吗?它也变得复杂,因为我必须使用事件传递变量,这不允许额外的参数。

    提前感谢您的帮助!如果你知道一个很好的网站,以更中间的方式解释Tkinter也会有所帮助!

    from Tkinter import *
    import tkMessageBox
    
    
    class MyWindow(Frame):
        def __init__(self, master):
                self.speeds = []
                Frame.__init__(self, master)
                self.speed_widgets()
    
        def speed_widgets(self):
                label = Label(self.master, text="Enter the speeds you want to process, seperated by a comma:")
                label = label.grid(row=0)
                self.speeds_text = Entry(self.master)
                self.speeds_text.grid(row=0, column=1)
                self.speeds_text.bind('<Return>', self.get_speeds)
    
    
        def get_speeds(self, event):
                #global speeds
                self.speeds = self.speeds_text.get()
                if (not self.speeds):
                        tkMessageBox.showerror('Invalid Entry','Please enter at least one speed.')
                else:
                        self.speeds = ''.join(self.speeds.split())
                        self.speeds = self.speeds.split(',')
                        num_speeds = len(self.speeds)
                        #print speeds
                self.bp_widget()
    
    
        def bp_widget(self):
                keys = []
                for speed in self.speeds:
                        keys.append(speed)
                self.bp = dict.fromkeys(keys)
    
                label = Label(self.master, text='Enter the back pressures for each speed, seperated by a comma:')
                label = label.grid(row=1)
    
                i = 2
                self.bp_text_widgets = []
                for speed in self.speeds:
                        label = Label(self.master, text=speed+'=')
                        label.grid(row=i, column=0)
    
                        self.bp_text_widgets.append(Entry(self.master))
                        self.bp_text_widgets[i-2].grid(row=i,column=1)
                        self.bp_text_widgets[i-2].bind('<Return>', lambda event, arg=i: self.get_bp(event, arg))
                        i += 1
    
        def get_bp(self, event, i):
                self.bp[self.speeds[i-2]] = self.bp_text_widgets[i-2].get()
                print self.bp[self.speeds[i-2]]
    
    
    root = Tk()
    MyWindow(root)
    root.mainloop()
    

1 个答案:

答案 0 :(得分:0)

关于全局变量的问题很容易回答。通常,最好避免使用它们。根据我所看到的情况,将这些值保存为属性是绝大多数人都会这样做的方式。

至于你在使用条目小部件做什么,我看到了一些问题。首先,如果我在第一个小部件中输入五个速度,然后按Enter,则会出现五个新的条目小部件。到现在为止还挺好。但是,如果我现在意识到我犯了一个错误并返回并删除了速度,我仍然有5个输入小部件。我已经玩过这个,添加和删除速度,我可以搞砸GUI。

其次,如果我在添加背压后忘记按Enter键,或者如果我在背压中纠正错误然后忘记按Enter键会发生什么?问题是我只看到输入,并且没有确认应用实际收到的内容。

这可能是一个品味问题,但我喜欢做的是弹出一个数据输入对话框,如果可能的话,在GUI的某处回显输入数据。所以,我会有一个标有“输入速度”的按钮,弹出一个用户输入速度的对话框。当他点击确定时,将创建一个标签,如“Speeds 70 80 90”。标签旁边会有一个“编辑”按钮,以防用户改变主意,或者想要输入新问题。

对于每个速度,我会弹出一个对话框,其中包含以下指令:“输入速度80的压力”。当用户单击“确定”时,将出现带有相关数据的标签和“编辑”按钮。

如果我理解你是对的,那么未使用的条目就是这样的原因是你不知道如何让它们消失。查找grid_forget方法。例如:

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/grid-methods.html

我希望我已经解决了你的问题。如果我错过了什么,请告诉我。

编辑:关于控制流程的“最佳方式”,当然,我没有答案。就个人而言,我喜欢让方法做一件事并返回。我会有另一个函数负责以正确的顺序调用数据输入方法。这样,数据输入方法是可分离的。如果用户意识到他忘记了什么,并且想要回去,我可以独立地打电话给他们。这可能也适用于您的设置,但我的交互并不是那么清楚。毫无疑问,这在很大程度上取决于我以前的习惯。尽管如此,我发现尽可能地使事物彼此独立,简化了未来的变化。另外,我不知道GUI有多少。如果您展示的内容几乎都是用户互动,那么我认为您所拥有的内容将完美无缺。