在python 2.7中从另一个类中获取/类变量/方法/widget.get()



我正在尝试编写一个利用Tkinter窗口切换OOP类的python程序。在起始页面上,有一个输入表单,用户可以在其中填写相关字段。在填写完表单后,点击"to tests"按钮,用户可以在切换框架/窗口后选择测试,并且由于该按钮在Startpage类中运行多个方法,因此输入的用户信息同时以。txt文件保存在指定的目录中。当通过单击test 1页面中的yes或no按钮接收数据时,就会出现问题。

该页在不同的类中操作,但需要从Startpage类中定义的get_info()方法返回值来获取输入的用户信息(文件名),以创建第二个.txt文件来存储原始数据,根据在测试1的GUI窗口中单击的按钮存储附加的"是"或"否"字符串。

然而,由于Test1没有从Startpage类/窗口接收任何条目数据,因此无法为第二个.txt文件分配文件名(调用包含widget.get()函数的get_info())。

信息是通过类中的方法正确获取的,一切工作正常。但是,当Test1请求从Startpage接收widget.get()变量/方法时,问题就出现了。

抛出的错误如下IndexError:

    Exception in Tkinter callback
    Traceback (most recent call last):
      File "C:UsersRylanAnacondaliblib-tkTkinter.py", line 1532, in     __call__
return self.func(*args)
      File "C:/Users/Rylan/Documents/Python/Basel Summerintern files/code to help with question.py", line 280, in update_countyes
directory = "C:UsersRylanDocumentsPythonBasel Summerintern files{}".format(self.get_t_info())
      File "C:/Users/Rylan/Documents/Python/Basel Summerintern files/code to help with        question.py", line 304, in get_t_info
        self.gettheinfo = Startpage(app, self.controller).get_info()
      File "C:/Users/Rylan/Documents/Python/Basel Summerintern files/code to help with question.py", line 170, in get_info
        str(Day) + "_" + str(Month) + "_" +
    IndexError: string index out of range

我对OOP编程非常陌生,据我所知,这可能是由以下原因引起的:

  • 没有正确地引用/调用Startpage实例,因此变量没有被Test1接收,因此调用get_info()方法导致在get_info()方法中嵌套的widget.get()函数/变量没有收到任何东西。

基本上,这个IndexError的原因是什么,我如何修复它,以获得创建/返回的文件名从get_info()方法在类Startpage发送到/由类Test1调用?

我看到过类似的问题,涉及到从不同的类调用类变量和方法,但是没有一个考虑到窗口/框架切换Tkinter应用程序的情况

下面是能够运行的简化代码(可能看起来不像)(您可能有目录路径存在问题,只需将路径更改为可以轻松定位的任何路径,以便保存.txt文件)

import Tkinter as tk
import ttk
import os
LARGE_FONT = ("Verdana", 12)
NORM_FONT = ("Verdana", 10)
SMALL_FONT = ("Verdana", 8)

def center(win):
    """
    centers a tkinter window
    param win: the window to center on the screen
    """
    win.update_idletasks()
    width = win.winfo_width()
    frm_width = win.winfo_rootx() - win.winfo_x()
    win_width = width + 2 * frm_width
    height = win.winfo_height()
    titlebar_height = win.winfo_rooty() - win.winfo_y()
    win_height = height + titlebar_height + frm_width
    x = win.winfo_screenwidth() // 2 - win_width // 2
    y = win.winfo_screenheight() // 2 - win_height // 2
    win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
    win.deiconify()

def popupmsg(msg):
    popup1 = tk.Tk()
    center(popup1)
    popup1.minsize(width=60, height=70)
    popup1.maxsize(width=60, height=70)
    popup1.wm_title("Attention!")
    label = ttk.Label(popup1, text=msg, font=NORM_FONT, anchor="center")
    label.pack(side="top", fill="x", pady=10)
    b1 = ttk.Button(popup1, text="Ok", command=lambda: popup1.destroy())
    b1.pack()
    popup1.mainloop()

class Testapp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.iconbitmap(self, default="testappicon2.ico")
        tk.Tk.wm_title(self, "Psychoacoustic Tests")
        container = ttk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
        menubar = tk.Menu(container)
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=lambda: self.destroy())
        menubar.add_cascade(label="File", menu=filemenu)
        tk.Tk.config(self, menu=menubar)
        self.frames = {}
        for F in (Startpage, TestSelect, Test1):
            frame = F(container, self)
            self.frames[F] = frame
            self.minsize(width=900, height=500)
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(Startpage)
    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

class Startpage(ttk.Frame):
    def __init__(self, parent, controller):
        ttk.Frame.__init__(self, parent)
        self.controller = controller
        self.titlelabel = ttk.Label(self, text="User Information", font = LARGE_FONT)
        self.titlelabel.grid(row=0, column=0, columnspan=4, padx = 10, pady = 10)
        self.firstnamelabel = ttk.Label(self, text="First Name: ", font = NORM_FONT)
        self.firstnamelabel.grid(row=1, column=0, sticky = 'w', padx = 15, pady = 10)
        self.lastnamelabel = ttk.Label(self, text="Last Name: ", font = NORM_FONT)
        self.lastnamelabel.grid(row=2, column=0, sticky = 'w', padx = 15, pady = 10)
        self.firstnameentry = ttk.Entry(self)
        self.firstnameentry.grid(row=1, column=1, padx=5, sticky = 'we', columnspan = 3)
        self.lastnameentry = ttk.Entry(self)
        self.lastnameentry.grid(row=2, column=1, padx=5, sticky = 'we', columnspan = 3)
        self.birthdaylabel = ttk.Label(self, text="Birthday: ", font = NORM_FONT)
        self.birthdaylabel.grid(row=3, column=0, sticky = 'w', padx = 15, pady = 10)
        self.daydropdown = ttk.Combobox(self, justify='center', height=20, width=2,
                                   values = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,
                                             15,16,17,18,19,20,21,22,23,24,25,
                                             26,27,28,29,30,31),
                                   state='readonly')
        self.daydropdown.grid(row=3, column=1, padx = 3, sticky = 'ew')
        self.monthdropdown = ttk.Combobox(self, justify='center', height=12, width=10,
                                     values = ('January','Feburary','March',
                                               'April','May','June','July',
                                               'August','September','October',
                                               'November','December'),
                                     state='readonly')
        self.monthdropdown.grid(row=3, column=2, padx=3, sticky = 'ew')            
        self.yeardropdown = ttk.Combobox(self, justify='center', height=20, width=4,
                                    values = (1980, 1981, 1982, 1983, 1984,
                                              1985, 1986, 1987, 1988, 1989,
                                              1990, 1991, 1992, 1993, 1994,
                                              1995, 1996, 1997, 1998, 1999),
                                    state = 'readonly')
        self.yeardropdown.grid(row=3, column=3, padx = 3, sticky = 'ew')
        self.genderlabel = ttk.Label(self, text="Gender: ", font = NORM_FONT)
        self.genderlabel.grid(row=4, column=0, sticky = 'w', padx = 15, pady = 10)
        self.var = tk.IntVar()
        self.Maleradio = ttk.Radiobutton(self, text='Male', variable=self.var, value = 1)
        self.Maleradio.grid(row=4, column=1, sticky = 'w')
        self.Femaleradio = ttk.Radiobutton(self, text='Female', variable=self.var, value = 2)
        self.Femaleradio.grid(row=5, column=1, sticky = 'w')
        self.emaillabel = ttk.Label(self, text="Email: ", font = NORM_FONT)
        self.emaillabel.grid(row=6, column=0, sticky = 'w', padx = 15, pady = 10)
        self.emailentry = ttk.Entry(self)
        self.emailentry.grid(row=6, column=1, columnspan=3, sticky='ew')
        self.experiencelabel = ttk.Label(self, text="Musical Experience: ", font = NORM_FONT)
        self.experiencelabel.grid(row=7, column=0, sticky = 'w', padx = 15, pady = 10)
        self.expdropdown = ttk.Combobox(self, justify='center', height=3, width=17,
                                   values = ('No experience', 'Some experience',
                                             'Musician level'), state='readonly')
        self.expdropdown.grid(row=7, column=1, columnspan=3, sticky = 'w')
        self.button1 = ttk.Button(self, text="To Tests", command= lambda: self.checkempty())
        self.button1.grid(row=8, column=3)

        def shortcut():
            controller.show_frame(TestSelect)
        buttonshort = ttk.Button(self, text="To Tests shortcut", command= lambda: shortcut())
        buttonshort.grid(row=9, column=3)

    def get_info(self):
        Name = self.firstnameentry.get()
        Surname = self.lastnameentry.get()
        Day = self.daydropdown.get()
        Month = self.monthdropdown.get()
        Year = self.yeardropdown.get()
        foldername = (str(Name[0]) + str(Surname[0]) +
                      str(Day) + "_" + str(Month) + "_" +
                      str(Year))
        return foldername
    def create_directory(self):
        if not os.path.isdir(self.get_info()):
            directory = "C:UsersRylanDocumentsPythonBasel Summerintern files{}".format(self.get_info())
            os.makedirs(directory)
            datafile = "{}_userinfo.txt".format(self.get_info())
            entirefile = os.path.join(directory, datafile)
            myfile = open(entirefile, 'w')
            myfile.write(self.userinfo())
            myfile.close()
            self.controller.show_frame(TestSelect)
        else:
            popupmsg("Folder already exists")
    def userinfo(self):
        Name = self.firstnameentry.get()
        Surname = self.lastnameentry.get()
        Day = self.daydropdown.get()
        Month = self.monthdropdown.get()
        Year = self.yeardropdown.get()
        Email = self.emailentry.get()
        Experience = self.expdropdown.get()
        def genderget():
            Gender = self.var.get()
            if Gender == 1:
                UserGender = "Male"
            elif Gender == 2:
                UserGender = "Female"
            return UserGender
        user_info = ("Participant Name: " + str(Name) + " " +
                     str(Surname) + "nBirthday: " + str(Day) + "_" +
                     str(Month) + "_" + str(Year) + "nGender: " +
                     str(genderget()) + "nEmail: " + str(Email) +
                     "nMusical Experience: " + str(Experience) +
                     "nDirectory Name: " + str(self.get_info()))
        return user_info
    def checkempty(self):
        Name = self.firstnameentry.get()
        Surname = self.lastnameentry.get()
        Day = self.daydropdown.get()
        Month = self.monthdropdown.get()
        Year = self.yeardropdown.get()
        Email = self.emailentry.get()
        Experience = self.expdropdown.get()
        if len(Name) == 0:
            popupmsg("Please complete the user information form")
        elif len(Surname) == 0:
            popupmsg("Please complete the user information form")
        elif Day == None:
            popupmsg("Please complete the user information form")
        elif Month == None:
            popupmsg("Please complete the user information form")
        elif Year == None:
            popupmsg("Please complete the user information form")
        elif self.var.get() == 0:
            popupmsg("Please complete the user information form")
        elif len(Email) == 0:
            popupmsg("Please complete the user information form")
        elif Experience == None:
            popupmsg("Please complete the user information form")
        else:
            self.create_directory()

class TestSelect(ttk.Frame):
    def __init__(self, parent, controller):
        ttk.Frame.__init__(self, parent)
        self.controller = controller
        label = ttk.Label(self, text="Select tests", font = LARGE_FONT)
        label.grid(row=0, column=0, columnspan=3)
        Test1Button = ttk.Button(self, text="Do test 1", command=lambda: controller.show_frame(Test1))
        Test1Button.grid(row=1, column=0, padx = 20, pady = 15, sticky = 'nsew')
        button2 = ttk.Button(self, text="Home", command=lambda: controller.show_frame(Startpage))
        button2.grid(row=3, column=2)

class Test1(ttk.Frame):
    def __init__(self, parent, controller):
        ttk.Frame.__init__(self, parent)
        self.controller = controller
        label = ttk.Label(self, text="Test 1", font = LARGE_FONT)
        label.grid(row=0, column=0, columnspan=2)
        button2 = ttk.Button(self, text="Page one", command=lambda: controller.show_frame(TestSelect))
        button2.grid(row=1, column=0, sticky = "w")
        yesbutt1 = ttk.Button(self)
        yesbutt1.grid(row=2, column=0)
        nobutt1 = ttk.Button(self)
        nobutt1.grid(row=2, column=1)
        yesbutt1['text'] = "Yes: 0"
        nobutt1['text'] = "No: 0"
        self.nobttn_clicks = 0
        self.yesbttn_clicks = 0
        def update_countyes():
            if self.yesbttn_clicks >= 1 or self.nobttn_clicks >= 1:
                popupmsg("Only one answer allowed!")
            else:
                self.yesbttn_clicks += 1
                yesbutt1['text'] = "Yes: " + str(self.yesbttn_clicks)
                directory = "C:UsersRylanDocumentsPythonBasel Summerintern files{}".format(self.get_t_info())
                datafile = "{}_test1data.txt".format(self.get_t_info())
                entirefile = os.path.join(directory, datafile)
                myfile = open(entirefile, 'a')
                myfile.write('nyes')
                myfile.close()
        def update_countno():
            if self.yesbttn_clicks >= 1 or self.nobttn_clicks >= 1:
                popupmsg("Only one answer allowed!")
            else:
                self.nobttn_clicks += 1
                nobutt1['text'] = "No: " + str(self.nobttn_clicks)
                directory = "C:UsersRylanDocumentsPythonBasel Summerintern files{}".format(self.get_t_info())
                datafile = "{}_test1data.txt".format(self.get_t_info())
                entirefile = os.path.join(directory, datafile)
                myfile = open(entirefile, 'a')
                myfile.write('nno')
                myfile.close()
        yesbutt1['command'] = update_countyes
        nobutt1['command'] = update_countno
    def get_t_info(self):
        self.gettheinfo = Startpage(app, self.controller).get_info()
        return self.gettheinfo
app = Testapp()
app.mainloop()

你的问题是当你写:

def get_t_info(self):
    self.gettheinfo = Startpage(app, self.controller).get_info()
    return self.gettheinfo

创建一个新的StartPage,其中条目为空。

    Name = self.firstnameentry.get()
    ...
    foldername = (str(Name[0])

尝试获取空字符串的第一个字符。

我认为解决方案应该是这样的:

def get_t_info(self):
    return self.controller.frames[Startpage]

最新更新