如何使用Tk文本框选择和绘制不同的数据集?

0 投票
2 回答
582 浏览
提问于 2025-05-01 05:28

我是一名刚接触Python 2.7和Tk的初学者,正在尝试创建一个图形界面,用来显示来自不同数据文件的图表。下面的程序框架使用了一个输入框,让用户输入“data1”和“data2”的名字。默认情况下,显示的是data1的图表。当有人输入“data2”并按下回车键时,我希望图表能切换到data2。

我尝试过用类和不使用类的方法,但都没有成功。

我也尝试过使用按钮,但也没有成功。

为什么dataname = etr.get()这行代码不起作用呢?

import sys
if sys.version_info[0] < 3:
    import Tkinter as tk
else:
    import tkinter as tk
from Tkinter import Label, Entry, Button, TOP, LEFT, BOTH #, Canvas, Frame, W, N, E, S

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

import numpy as np

def plot_data(fig, dat_name):
    t = np.arange(10)
    v1 = [1,2,3,4,5,4,4,4,4,4]
    v2 = [4,4,4,4,5,4,4,3,2,1]
    if dat_name[4] == 2:
        y = v2
    else:
        y = v1
    a = fig.add_subplot(111)
    a.plot(t,y, color='red')
    a.set_title('Graph of ')    
    a.set_xlabel('time (s)')
    a.set_ylabel('voltage (mv)')

root = tk.Tk()
root.geometry("500x250+200+200")
dataname = 'data1'

f = Figure(figsize=(4,3), dpi=72)
canvas = FigureCanvasTkAgg(f, master=root)
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)

#plot_data(f, dataname)

lbl = Label(root, text='Current data:  ')
lbl.pack(side=LEFT)

etr = Entry(root, width=20)
etr.pack(side=LEFT)
etr.delete(0, last=None)
etr.insert(0, dataname) # What is the first parameter for???
dataname = etr.get()

#etr_entry.bind("<Return>", entry_handler)
#btn = Button(root, text = 'Open', command=entry_handler)
#btn.pack(side=LEFT)

plot_data(f, dataname)
print('dataname = '+dataname)
root.mainloop()  
暂无标签

2 个回答

0

Arthur,非常感谢你的回答。你提出了很多好的建议。与此同时,我继续工作,创建了一个新的类叫做CardioGUI。最后,我得到了以下结果:

http://imagizer.imageshack.us/a/img661/3842/zTESMt.png

这是我目前的代码(可以显示图表,不过还有一些小问题)

import numpy as np

from Tkinter import Label, Button, StringVar, LEFT, TOP, BOTH
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

import sys
if sys.version_info[0] < 3:
    import Tkinter as tk
else:
    import tkinter as tk

def destroy(e): sys.exit()

#root.bind("<Destroy>", destroy)

class CardioGUI:
    LABEL_TEXT = [
        "Example-30s",
        "Example-120s",
        "David-counting",
        "Cynthia-following",
        "Miriam-reading"
     ]
    def __init__(self, master):
        self.master = master
        master.title("Cardiorespiratory GUI")
        self.f = Figure(figsize=(4,3), dpi=72)
#        self.f.set_facecolor('red')

        self.label_index = 0
        self.label_text = StringVar()
        self.label_text.set(self.LABEL_TEXT[self.label_index])
#        plot_data(self.label_text.get())

        self.cvs = FigureCanvasTkAgg(self.f, master=root)
        self.cvs.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        self.cvs._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)

        self.lbl1 = Label(master, text='Data') # Non-interactive label
        self.lbl1.pack(side=LEFT)

        self.lbl2 = Label(master, width=30, textvariable=self.label_text)
        self.lbl2.bind("<Button-1>", self.cycle_label_text)
        self.lbl2.pack(side=LEFT)

        self.btn1 = Button(master, text='Plot data')
        self.btn1.bind("<Button-1>", \
          lambda label_text: plot_data(self.label_text.get()))
        self.btn1.pack(side=LEFT)

        self.greet_button = Button(master, text="Analyze", command=self.greet)
        self.greet_button.pack(side=LEFT)

    def greet(self):
        print("Analyse!")

    def cycle_label_text(self, event):
        self.label_index += 1
        self.label_index %= len(self.LABEL_TEXT) # wrap around
        self.label_text.set(self.LABEL_TEXT[self.label_index])
        plot_data(label_text.get())

def plot_data(session_name):
    a = my_gui.f.add_subplot(211)
    b = my_gui.f.add_subplot(212)

    my_gui.cvs.show()

    filepath = 'C:/Users/David/My Documents/Cardiorespiratory Experiment/data/'
    fullfilename = filepath+session_name+'.txt'

    data = np.loadtxt(fullfilename, skiprows=7, usecols=(0,1,2))
    t = [row[0] for row in data]    
    v = [row[1] for row in data]
    p = [row[2] for row in data]

    a.plot(t,v, color='red')
    a.set_title('Heartbeat and Respiration')
    a.set_xlabel('time (s)')
    a.set_ylabel('voltage (mv)')
    b.plot(t,p)
    b.set_xlabel('time (s)')
    b.set_ylabel('pressure (kpa)')
    return # Unclear whether this is needed


root = tk.Tk()
root.geometry("500x250+100+100")
my_gui = CardioGUI(root)
root.mainloop()
0

这里有一个有效的解决方案:

import sys
if sys.version_info[0] < 3:
    import Tkinter as tk
else:
    import tkinter as tk
from Tkinter import Label, Entry, Button, TOP, LEFT, BOTH #, Canvas, Frame, W, N, E, S

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

import numpy as np

class ECG_Dsiplayer(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)

        master.bind("<c>", lambda x : self.clean())#allow to test the clean function, press "c"
        master.bind("<Return>", lambda x : self.draw_data())

        self.datasetName = tk.StringVar()
        self.datasetName.set("data1") #default value
    # ____________________________________________________  
    def draw_data(self):
        self.clean()
        self._createWidgets()
        self.plot_ecg_data()
    # ____________________________________________________
    def plot_ecg_data(self):
        values = self._load_data(self.datasetName.get())
        a = self.figure.add_subplot(111)
        a.plot(np.arange(len(values)),values, color='red')
        a.set_title('Graph of ')    
        a.set_xlabel('time (s)')
        a.set_ylabel('voltage (mv)')
    # ____________________________________________________
    def _createWidgets(self):
        self.figure = Figure(figsize=(4,3), dpi=72)

        self.canvas = FigureCanvasTkAgg(self.figure, master=self)
        self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
        self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)

        self.label = Label(self, text='Current data:  ')
        self.label.pack(side=LEFT)

        self.datasetEntry = Entry(self, width=20, textvariable=self.datasetName)
        self.datasetEntry.pack(side=LEFT)
    # ____________________________________________________  
    def _load_data(self, dataName):
        ## TO OVERRIDE IN ORDER TO PROVIDE A TRUE DATA LOADING SYSTEM ##
        if dataName == "data1":
            return [1,2,3,4,5,4,4,4,4,4]
        else:
            return [4,4,4,4,5,4,4,3,2,1]
    # ____________________________________________________  
    def clean(self):
        for widget in self.pack_slaves():
            widget.pack_forget()
    # ____________________________________________________


if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("500x250+200+200")    

    ecg = ECG_Dsiplayer(root)
    ecg.pack(fill=BOTH, expand=1)

    ecg.draw_data()

    root.mainloop()

请注意以下几点:

  • 你用来检查哪个数据集的测试有问题。它总是返回相同的值,所以你的问题可能出在这一行。if dat_name[4] == 2: 这个条件总是为假,因为你在比较一个整数和一个字符串。
  • 你应该使用更明确的变量名。我在这里做了一些重构,但整体代码的可读性还有待提高!
  • 你应该尝试使用网格管理器,而不是打包管理器。打包管理器可以快速构建图形界面,但网格管理器能更好地控制发生了什么。在这里,使用网格管理器可以只删除画布小部件,而不影响其他部分。这也允许你把输入框和标签的代码放在初始化方法中,并且之后不再调用。使用打包管理器的话,如果不删除,它们会在第二次绘制数据时一起上移。

最后,祝你在学习Python的过程中玩得开心,祝好运!

Arthur.

撰写回答