0

I want to access the entry widget via the get() method, not the variable. The problem is I can´t seem to make the entry as variable accessible in other methods. The widget I am talking about is the trennzeichenentry widget from my menubaroptions method. Here is a snippet of my code:

import tkinter
from tkinter.constants import *
from tkinter import messagebox
from struct import unpack
from codecs import decode

class Graphicaluserinterface(tkinter.Frame):

    @classmethod
    def main(cls):
        root = tkinter.Tk()
        root.title('Hex2Dec_Converter_APS300')
        root.minsize(560, 105)
        gui = cls(root)
        gui.grid(row=0, column=0, sticky=NSEW)
        root.grid_rowconfigure(0, weight=1)
        root.grid_columnconfigure(0, weight=1)
        root['menu'] = gui.menubar
        root.mainloop()

    def __init__(self, master=None):
        super().__init__(master)
        for rowconfigure in range(5):
            self.master.grid_rowconfigure(rowconfigure,weight=1)
        for columnconfigure in range(4):
            self.master.grid_columnconfigure(columnconfigure,weight=1)
        frame1 = tkinter.Frame(master)
        frame1.grid(row=0,column=0,rowspan=5,columnspan=1,sticky=NSEW)
        frame1.columnconfigure(0,weight=1)
        frame2 = tkinter.Frame(master)
        frame2.grid(row=0,column=1,rowspan=5,columnspan=3,sticky=NSEW)
        frame2.columnconfigure(1,weight=2)
        frame2.rowconfigure(0,weight=0)
        frame2.rowconfigure(1,weight=6)
        frame2.rowconfigure(2,weight=0)
        frame2.rowconfigure(3,weight=1)
        frame2.rowconfigure(4,weight=2)
        self.entrystring = tkinter.IntVar()
        self.taktzykluszeit = tkinter.DoubleVar()
        self.menubar = tkinter.Menu(self)
        self.file_menu = tkinter.Menu(self.menubar, tearoff=FALSE)
        self.help_menu = tkinter.Menu(self.menubar, tearoff=FALSE)
        self.create_widgets()

    def create_widgets(self):
        self.menubar.add_cascade(label="File", menu=self.file_menu)
       self.file_menu.add_command(label="Options",command=self.menubaroptions)

    def menubaroptions(root):
        optionswindow = tkinter.Toplevel(root)
        optionswindow.title("Options")
        optionswindow.minsize(300,150)
        trennzeichenlabel = tkinter.Label(optionswindow,text="Length of Separator in Byte:")
        trennzeichenlabel.pack()
        trennzeichenentry = tkinter.Entry(optionswindow,textvariable=root.entrystring,width=30,justify="center")
        trennzeichenentry.pack()
        taktzykluszeitlabel = tkinter.Label(optionswindow,text="Measurementtime for all \n Temperature-Sensors in sec")
        taktzykluszeitlabel.pack()
        taktzykluszeitentry = tkinter.Entry(optionswindow,textvariable=root.taktzykluszeit,width=30,justify="center")
        taktzykluszeitentry.pack()

    def methodiwanttocallthevariablein(self):
        #call trennzeichenentry here

if __name__ == '__main__':
    Graphicaluserinterface.main()

So how can I make "trennzeichenentry" into a variable and call it in the method "methodiwanttocallthevariablein" ? I always got NameError when trying around myself. I am not quite sure what is different here than to my other methods and variable I have.

Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
James
  • 317
  • 3
  • 12

1 Answers1

1

When defining a variable inside of a function if you do not use global then the function will assume you want to assign that variable locally only. This will basically mean that nothing else in your code can access that variable unless you mark it as global or pass it directly to another function.

So add this:

global trennzeichenentry

In the menubaroptions function like this:

def menubaroptions(root):
     global trennzeichenentry

You will also need to define the global in your other method as well. All that said you really don't want to use global in a class and your class should be reworked to compensate for this properly.

Here is a simplified version of your code that shows how to set up your entry fields as a class attribute so you can avoid global variables.

import tkinter as tk


class GraphicalUserInterface(tk.Tk):
    def __init__(self):
        super().__init__()
        self.minsize(560, 105)
        self.entry_string = tk.IntVar()
        self.taktzykluszeit = tk.DoubleVar()
        self.menubar_options()
        tk.Button(self, text='print entries', command=self.method_i_want_to_call_the_variable_in).grid()

    def menubar_options(self):
        optionswindow = tk.Toplevel(self)
        optionswindow.minsize(300, 150)
        tk.Label(optionswindow, text="Length of Separator in Byte:").pack()
        self.trennzeichenentry = tk.Entry(optionswindow, textvariable=self.entry_string, width=30, justify="center")
        self.trennzeichenentry.pack()
        tk.Label(optionswindow, text="Measurementtime for all \n Temperature-Sensors in sec").pack()
        self.taktzykluszeitentry = tk.Entry(optionswindow, textvariable=self.taktzykluszeit, width=30, justify="center")
        self.taktzykluszeitentry.pack()

    def method_i_want_to_call_the_variable_in(self):
        print(self.trennzeichenentry.get())
        print(self.taktzykluszeitentry.get())

if __name__ == '__main__':
    GraphicalUserInterface().mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • why is the use of a global variable not recommended in this case ? i will try to implement your code and try it out – James Jan 16 '19 at 17:24
  • the problem is, that with your code the menubar_options window pops up as soon as i run the program, which i dont want, and i get an "_tkinter_TclError: invalid command name" – James Jan 16 '19 at 17:44
  • @James I removed the irrelevant code to the issue. My code example is just to show how you use class attributes to access variables in different methods. You can easily add you menu in and change the call to `menubar_options()`. As for why you want to avoid global variables there is a good post about that here: [Why are global variables evil?](https://stackoverflow.com/questions/19158339/why-are-global-variables-evil) – Mike - SMT Jan 16 '19 at 18:04
  • i had a problem with my classmethod which i avoided by creating self.tzeget=self.trennzeichenentry.get() which i can call in another method. Though i have a question: is there a way to call and thus create the objects of the menubaroptions method BUT NOT creating the pop up window(yet still letting the user do so by clicking in the menubar) ? Since this only works when the object have been created – James Jan 16 '19 at 18:10
  • @James sure. That is usually what the `StringVar()/IntVar()`'s are for. You can define the variables in the `__init__` method and just access them once your window pops up. – Mike - SMT Jan 16 '19 at 18:52
  • the problem is that an IntVar() cuts everything off after the decimal separator, and i don´t know how to check wether a DoubleVar() is an actual Double or something like 2.0 , 5.0 etc. Since my maingoal is to check if the user put the right input – James Jan 16 '19 at 18:55
  • Then use a `StringVar()`. This will keep the exact number the user puts in, then you can test if the value of `StringVar().Get()` is equal to a valid double and convert to a float and do the math you need to do. `StringVar().Get().isdecimal()` will tell you if the string is a valid number. Could be any number also. – Mike - SMT Jan 16 '19 at 18:58