简体   繁体   中英

Variable not sharing same value between two different functions Python 2.7 Tkinter

I would need to create a Python 2.7 script using Tkinter which should do the following:

When clicking on the "Create the NWs" button in a window -> I should see a field and a "Add network" button near the field. If I have more than one field to introduce, then I should press on the "Add network" button and see another field afterwards to fill in. If I have one or more than one field completed => should write in the file according to the "for" described in the define function. If I do not have any field completed, the file should not be created

The Tkinter part is doing what it should, but the code is not writing it correctly in the file. Here is the relevant part inside of a class where the problem is:

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

    def create_widgets(self):
        label = tk.Label(self, text="Insert the name of the networks")
        start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
        new_network_button = tk.Button(self, text="Add network", command=self.add_network)
        new_network_button.bind("<Return>", self.add_network)
        new_network_button.grid(row=len(self.master.networks), column=3, padx=4, pady=6, sticky="W")
        next_button=tk.Button(self, text="Next", command=self.networks)
        next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
        label.pack(side="top", fill="x", pady=10)
        start_button.pack()
        new_network_button.pack()
        next_button.pack()
        for index, network in enumerate(self.master.networks):
            self.render_network_field(network, index)

    def add_network(self):
        self.master.networks.append({'variable': tk.StringVar(self.master)})
        self.master.switch_frame(Networks)

    def render_network_field(self, network, index):
        entry_field = tk.Entry(self, textvariable=network['variable'])
        entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
        entry_field.pack()
        global s
        s=entry_field.get()  
        print hex(id(s)) 

    def networks(self):
        with open("/home/dante/networks.yml", "w") as f:
             f.write("--- #" + "\n")
             f.write("networks:" + "\n")
             print hex(id(s))
             for ent in s:
                 if ent:
                    f.write("- { cloud: cloud1, network: "+str(ent)+ " }"+ "\n")

Now, the file is written just like this, like "s" is not existing:

--- #
networks:

I have printed the hex id in "render_network_field" and in "networks" functions and it is seems that the "s" IDs are different. I thought that the "s" has the same value in both functions. That's the reason that I am getting nothing written in the file.

Any idea how I can correct this?

PS Please note that I am quite new to programming.

Note : In the beginning of this answer, I am describing a cleaner way to accomplish what you are trying to do. However, if you do want to use globals, I have described how that would be done at the end of my answer

You must first declare the s variable in the class's scope . If you declare it only in the function, it assumes the function's scope.

This would be as follows:

class Networks(tk.Frame):
    # Dummy definition. The real value will be filled in later
    s = None

Or, to be more clear, you could use the self variable. Note the lines where s is used. This would work as follows

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

    def create_widgets(self):
        label = tk.Label(self, text="Insert the name of the networks")
        start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
        new_network_button = tk.Button(self, text="Add network", command=self.add_network)
        new_network_button.bind("<Return>", self.add_network)
        new_network_button.grid(row=len(self.master.networks), column=3, padx=4, pady=6, sticky="W")
        next_button=tk.Button(self, text="Next", command=self.networks)
        next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
        label.pack(side="top", fill="x", pady=10)
        start_button.pack()
        new_network_button.pack()
        next_button.pack()
        for index, network in enumerate(self.master.networks):
            self.render_network_field(network, index)

    def add_network(self):
        self.master.networks.append({'variable': tk.StringVar(self.master)})
        self.master.switch_frame(Networks)

    def render_network_field(self, network, index):
        entry_field = tk.Entry(self, textvariable=network['variable'])
        entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
        entry_field.pack()
        self.s=entry_field.get()  
        print hex(id(self.s)) 

    def networks(self):
        with open("/home/dante/networks.yml", "w") as f:
             f.write("--- #" + "\n")
             f.write("networks:" + "\n")
             print hex(id(self.s))
             for ent in self.s:
                 if ent:
                    f.write("- { cloud: cloud1, network: "+str(ent)+ " }"+ "\n")

Finally, if you really wanted it to be global, you must declare it as a global at the top of every function.

...
    def networks(self):
        global s
...

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