Search code examples
pythonpython-3.xtkinternonetypetkinter-entry

Python: 'NoneType' object has no attribute 'get'


I'm creating a GUI in python using tkinter and am having trouble when running it. I have an entry box widget, a radiobutton widget, and a button widget. When I press the button, what I want is the user to type a number into the entry box and select an option from the list of radiobuttons. When the user presses the button, I'd like the values to be retrieved and displayed in the other frame for testing. What I get instead is when the button gets pressed, I get the error 'NoneType' object has no attribute 'get'. The error is referring to the value inside of the entry box: self.tune_entry

The code I have is as follows:

SA_main.py

import os
import tkinter as tk
from tkinter import ttk
from tkinter import font
import SA_gui

def main():

    x_vals = [0,1,2,3,4]
    y_vals = [0,1,2,3,4]

    root = SA_gui.tk.Tk()
    UI = SA_gui.Window(root, x_vals, y_vals)

    root.mainloop()


if __name__ == "__main__":
    main()

SA_gui.py

import os
import tkinter as tk
from tkinter import ttk
from tkinter import font

# Class to define, setup, and build the GUI
class Window:

    # Dimensions of the GUI
    HEIGHT = 600
    WIDTH = 1200

    # Colors for main layout
    bg_color = "#B0E0E6"
    frame_color1 = "#73B1B7"
    white_color = "#FFFFFF"

    def __init__(self, master, x_vals, y_vals):

        # Take in the lists of files for later use
        self.x_vals = x_vals
        self.y_vals = y_vals

        #--------------------------------------------------------------

        # Define and create the window
        self.master = master
        master.title("Signal Analysis")
        master.geometry("{}x{}".format(Window.WIDTH, Window.HEIGHT))

        # Create and place the background frame
        self.bg_frame = tk.Frame(self.master, bg=Window.bg_color, bd=5)
        self.bg_frame.place(relwidth=1, relheight=1)

        # Create the main title
        self.main_title = tk.Label(self.bg_frame, text="Software Defined Radio Signal Analysis", 
            bg=Window.bg_color, font=("Courier", 14))
        self.main_title.pack(side="top")

        #--------------------------------------------------------------

        # Create and place the frame for tuning
        self.tune_frame = tk.Frame(self.bg_frame, bg=Window.frame_color1, bd=4)
        self.tune_frame.place(relx=0.05, rely=0.1, relwidth=0.2428, relheight=0.8)

        # Create and place the title for the tuning frame
        self.tune_title = tk.Label(self.tune_frame, text="Tune", bg=Window.frame_color1, font= 
            ("Courier", 11))
        self.tune_title.place(relwidth=1, anchor="nw")

        # Create and place the contents of the tuning frame
        self.tune_cont = tk.Frame(self.tune_frame, bg=Window.white_color, bd=4)
        self.tune_cont.place(relx=0.05, rely=0.05, relwidth=0.9, relheight=0.925)

        #Label for frequency entry
        self.tune_label = tk.Label(self.tune_cont, text='Enter carrier frequency: (kHz)', 
            bg=Window.white_color)
        self.tune_label.place(relx=0.025, rely=0)

        #Entry Box for frequency entry
        self.tune_entry = tk.Entry(self.tune_cont)
        self.tune_entry.place(relx=0.025, rely=0.075, relwidth=0.95, relheight=0.05)

        #Label for divider
        self.tune_div = ttk.Separator(self.tune_cont, orient="horizontal")
        self.tune_div.place(rely=0.175, relwidth=1)

        #Label for display mode
        self.disp_label = tk.Label(self.tune_cont, text='Select Display:', bg=Window.white_color)
        self.disp_label.place(relx=0.025, rely=0.2)

        #Variable for radiobuttons
        self.var = tk.IntVar(self.tune_cont).set("1")

        #Radio Button for Spectral Analysis
        self.SA_select = tk.Radiobutton(self.tune_cont, text="Spectral 
            Analysis",bg=Window.white_color, padx=20, variable=self.var, value=1)
        self.SA_select.place(relx=0.025, rely=0.275)

        #Radio Button for Option 2
        self.opt2_select = tk.Radiobutton(self.tune_cont, text="Option 2",bg=Window.white_color, 
            padx=20, variable=self.var, value=2)
        self.opt2_select.place(relx=0.025, rely=0.35)

        #Radio Button for Option 3
        self.opt3_select = tk.Radiobutton(self.tune_cont, text="Option 3",bg=Window.white_color, 
            padx=20, variable=self.var, value=3)
        self.opt3_select.place(relx=0.025, rely=0.425)


        #Button for selection
        self.tune_button = ttk.Button(self.tune_cont, text="Enter", command=lambda: 
            self.print_selected(self.var.get(), self.tune_entry.get()))
        self.tune_button.place(relx= 0.775, rely=0.9, relwidth=0.2, relheight=0.075)

        #-----------------------------------------------------------------

        # Create and place the frame for the plot
        self.plot_frame = tk.Frame(self.bg_frame, bg=Window.frame_color1, bd=4)
        self.plot_frame.place(relx=0.3428, rely=0.1, relwidth=0.6071, relheight=0.8)

        # Create and place the title for the plot frame
        self.plot_title = tk.Label(self.plot_frame, text="Plot", bg=Window.frame_color1, font= 
            ("Courier", 11))
        self.plot_title.place(relwidth=1, anchor="nw")

        # Create and place the contents of the plot frame
        self.plot_cont = tk.Frame(self.plot_frame, bg=Window.white_color, bd=4)
        self.plot_cont.place(relx=0.025, rely=0.05, relwidth=0.95, relheight=0.925)



    def print_selected(self, disp, freq):
        if disp == 1:
            disp_mode = "Spectral Analysis"
        elif disp == 2:
            disp_mode = "Option 2"
        else:
            disp_mode = "Option 3"

        #Label for this test
        self.prnt_label = tk.Label(self.plot_cont, text="Display: " + disp_mode + ", Center Freq: " + 
            freq, bg=Window.white_color)
        self.prnt_label.place(relx=0.025, rely=0.2)

Any help to resolve this issue is greatly appreciated!


Solution

  • Consider this code:

    self.var = tk.IntVar(self.tune_cont).set("1")
    

    Anytime you do x=y().z() python assigns the return value of z() to x. Thus, in your code you're assiging the result of .set("1") to self.var. The set method is returning None so self.var is None. Thus, when you later try to call self.var.get() it's the same as doing None.get().

    If you want to initialize a variable at the time of creation, there is no need to call set. Also, while it works to pass a string, if you're setting an IntVar you really ought to be setting it to an integer.

    self.var = tk.IntVar(value=1)