简体   繁体   中英

Calling textvariable from function within a class Python 3 tkinter

Thankful for any assistance in my question.

I am using Python 3 with tkinter where I have setup multiple pages, however I am trying to call a specific textvariable which is in a class, within a definition and wondering if it's possible to do with the way I built my script.

It's quite a big script so I don't want to paste all the code here, I hope this will be enough.

Basically the class is called POIIN(tk.frame) and I am trying to call

class POPage(tk.Frame):
def __init__(self, parent, controller):
    tk.Frame.__init__(self, parent)

    self.entryboxes()

def entryboxes(self):
    # Entry boxes + variables
    global voucher
    voucher = IntVar()
    entry_box3 = tk.Entry(self, textvariable=voucher, width=32, bg="lightgreen")
    entry_box3.place(x=435, y=151)

I am trying to call the textvariable by doing the following outside of the class:

def do_mssql():
try:
    if int(POPage.entryboxes(voucher).get()) > int(maxN):
        voucherchktext()
    elif int(voucher.get()) < int(minN):
        voucherchktext()

    else:
        sql()
except:
    vouchermissing()

However it seems to be calling the IntVar() and I don't get any error message, (quite new with Python) Basically I can pull the voucher from another class (page) with just doing the int(voucher.get()). I could of course rename the textvariable and call it that way (which I don't mind), but it would be great if there is any way around this.

Greatful for any help!

BR,

Thanks for posting your entire code on pastebin. By looking at your code I can see that none of your classes actually take ownership of the tkinter widgets they create. In otherwords, they don't have any instance variables. I would suggest a radical redesign and getting rid of all global variables and objects - in this case it's a major code smell and suggests that there is a flaw in your design - and that's fine, you did say you were a beginner after all. I see a lot of good things in your code, too. Not to be one-sided...

Basically, the change I'm recommending is this: Each frame class should take ownership of the widgets they create. That includes things like tk.Label s, tk.Button s, tk.Entry s and tk.IntVar s among others.

The major benefit this provides, is that any instance of your frame class will have its own tk.IntVar (or whatever entry widget variable, like tk.StringVar ) which it does not need to share with any of the other classes (you called it a textvariable ). This makes sense if you think about it: Every tk.Entry widget is coupled with one variable object that keeps track of the user's entered data for that entry widget - if you create just one global entry variable and share it with all entry widgets in all frames, you could easily lose a user's entered data - there's really no reason to do that.

Try running/playing around with the following code snippet:

import tkinter as tk


class MyFrame(tk.Frame):

    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

        self.label = tk.Label(self, text="Some Text")
        self.label.pack()

        self.entry_var = tk.IntVar()
        self.entry = tk.Entry(self, textvariable=self.entry_var, width=32)
        self.entry.pack()

        self.button = tk.Button(self, text="Print this frame's 'entry_var'", command=lambda: print(self.entry_var.get()))
        self.button.pack()


class Application(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title("Title")
        self.geometry("256x256")
        self.resizable(width=False, height=False)

        self.frames = []

        for frame in MyFrame(), MyFrame():
            self.frames.append(frame)
            frame.pack()

def main():

    application = Application()
    application.mainloop()

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

You have a main Application (you call it Ghost in your example), which has multiple frames (my example only has one frame class, but the Application has two instances of that frame class). Each frame instance has an entry widget and a unique, completely separate and distinct corresponding entry variable object. There is no reason for frames to share the same entry variable object. Making the widgets and entry variable objects instance variables of their classes should eliminate your use of global variables entirely.

In my example, if I needed to get access to the values in the entry widgets from outside the classes - like in the main function for example, you would say application.frames[0].entry_var.get() to get the value in the first frame's entry widget.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM