Python Forum
Using Tkinter widgets on child window
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Using Tkinter widgets on child window
#1
Main/Root Window

My issue is in the TopLevel/Secondary Window. In that class, I have a ListBox which I can declare successfully and will appear, but my end goal is to have a button on that screen call a secondary function which will then populate the Listbox with some data from a DB.

Before tackling the database logic I tried to simply just put some data in manually using the below method:
self.Lb1.insert(END, "Entry Value")
But for some reason, it doesn't recognize that command which results in the following error
AttributeError: 'NoneType' object has no attribute 'insert'

Any help would be appreciated :)

from tkinter import *
from tkinter import ttk

class Application(object):
    def __init__(self, master):
        self.topColor = '#f2f2f2'
        self.bottomColor = '#e6e6e6'

        self.master = master

        # Configure our menu
        menu = Menu(self.master)
        self.master.config(menu = menu)

        file = Menu(menu, tearoff = 0)
        file.add_command(label = 'About', command = self.aboutMessage)
        file.add_command(label = 'Exit', command = self.client_exit)
        menu.add_cascade(label = 'File', menu = file)

        edit = Menu(menu, tearoff = 0)
        edit.add_command(label = 'Undo')
        menu.add_cascade(label = 'Edit', menu = edit)

        rules = Menu(menu, tearoff = 0)
        rules.add_command(label = 'Add Table & Function', command = self.addFuncTable)
        rules.add_command(label = 'Search', command = self.search)
        menu.add_cascade(label = 'Rules', menu = rules)

        # ---- Top Frame ---- #
        # Configure frames
        self.top = Frame(master, height = 71, bg = self.topColor)
        self.top.pack(fill = X)
        self.bottom = Frame(master, height = 530, bg = self.bottomColor)
        self.bottom.pack(fill = X)

        self.top_image = PhotoImage(file ='Images/Logo.png')
        Label(self.top, image = self.top_image).place(x = -1, y = -1)

        Label(self.top, text = "H03 & HF9 Mosaic Script Generation Tool", bg = self.topColor, font = ('Calbri', 11)).place(x = 70, y = 5)
        Label(self.top, text = 'Use the below entry boxes to fill in the necessary information about your ITR', bg = self.topColor).place(x = 70, y = 30)
        Label(self.top, text = 'This will include your Version Number(s), GUID, etc', bg = self.topColor).place(x = 70, y = 48)

        # ---- Bottom Frame ---- #

        # Define var's for each of our fields so we can get the value
        self.entry_appendixPath = StringVar()
        self.entry_rateSheetPath = StringVar()


        Label(self.bottom, text = 'File Path for Appendix:', bg = self.bottomColor).place(x = 4, y = 20)
        self.appendix = ttk.Entry(self.bottom, width = 30, textvariable = self.entry_appendixPath).place(x = 7, y = 40)

        Label(self.bottom, text = "File Path for Rate Sheet:", bg = self.bottomColor).place(x = 250, y = 20)
        self.rateSheet = ttk.Entry(self.bottom, width = 30, textvariable = self.entry_rateSheetPath).place(x = 253, y = 40)

        Label(self.bottom, text = "Script Author:", bg = self.bottomColor).place(x = 4, y = 80)
        ttk.Entry(self.bottom).place(x = 7, y = 100)

        Label(self.bottom, text = "GUID Identifier:", bg = self.bottomColor).place(x = 170, y = 80)
        ttk.Entry(self.bottom).place(x = 173, y = 100)

        self.StateCodeVal = StringVar()
        Label(self.bottom, text = "State Code:", bg = self.bottomColor).place(x = 350, y = 80)
        ttk.Combobox(self.bottom, textvariable = self.StateCodeVal, width = 10, values = [
            "PA", "AK", "AZ", "AR", "CA", "CO", "CT", "DC", "DE", "FL", "GA",
            "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA",
            "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY",
            "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX",
            "UT", "VT", "VA", "WA", "WV", "WI", "WY"
        ]).place(x = 353, y = 100)

        Label(self.bottom, text = "Current Version", bg = self.bottomColor).place(x = 4, y = 135)
        ttk.Entry(self.bottom).place(x = 7, y = 155)

        Label(self.bottom, text = "New Version:", bg = self.bottomColor).place(x = 170, y = 135)
        ttk.Entry(self.bottom).place(x = 173, y = 155)

        Label(self.bottom, text = "UW Company:", bg = self.bottomColor).place(x = 350, y = 135)
        ttk.Entry(self.bottom, width = 10).place(x = 353, y = 155)

        Button(self.bottom, text="Lookup Version", command=self.lookupOldVersion).place(x=6, y=180)

        # Not an easy way to execute a stored proc in python with OUTPUT params
        # Button(self.bottom, text="Generate").place(x = 173, y = 180)

        Label(self.bottom, text="Above button call requires that both State Code and Apex Flag are valued!", bg = self.bottomColor, fg="Red").place(x = 4, y = 210)

        self.ApexCheck = StringVar()
        Label(self.bottom, text="Apex Flag ( 1 -> is Apex, 0 -> Legacy):",
              bg=self.bottomColor).place(x = 4, y = 250)
        ttk.Combobox(self.bottom,  textvariable=self.ApexCheck, width = 10, values = [
           1, 2
        ]).place(x = 4, y = 272)

        Label(self.bottom, text = "Do we need to create new procedure(s) or table(s) for this ITR?", bg = self.bottomColor).place(x = 4, y = 310)

        # Set style for ttk.RadioButton since bg= is not supported
        s = ttk.Style()
        s.configure(
            'myStyle.TRadioButton',
            background = self.bottomColor
        )

        self.newCheck = IntVar()
        ttk.Radiobutton(self.bottom, text = "Yes", variable = self.newCheck, value = 1).place(x = 5, y = 335)
        ttk.Radiobutton(self.bottom, text = "No", variable = self.newCheck, value = 0).place(x = 5, y = 360)

        # Radiobutton(self.bottom, text = "Yes", bg = self.bottomColor, variable = newCheck, value = 1).place(x = 4, y = 270)
        # Radiobutton(self.bottom, text = "No", bg = self.bottomColor, variable = newCheck, value = 0).place(x = 4, y = 290)

        # Checkbutton(self.bottom, bg = self.bottomColor, text = "Yes", variable = newCheck).place(x = 4, y = 270)

        Button(self.bottom, text = 'Submit', fg = 'white', bg = '#00802b', command = self.getEntries).place(x = 4 , y = 400)


    def search(self):
        S = Search.Search()


def main():
    root = Tk()
    app = Application(root)
    root.title('Main Window')
    root.geometry('500x600')
    root.resizable(False, False)
    root.mainloop()

if __name__ == '__main__':
    main()
Second Window

# Tkinter modules
from tkinter import *
from tkinter import ttk
from tkinter import messagebox

class Search(Toplevel):
    def __init__(self):
        Toplevel.__init__(self)

        self.geometry('500x500')
        self.title('Search')
        self.resizable(False, False)

        self.topColor = '#f2f2f2'
        self.bottomColor = '#e6e6e6'

        # Configure frames
        self.top = Frame(self, height=71, bg=self.topColor)
        self.top.pack(fill=X)
        self.bottom = Frame(self, height=430, bg=self.bottomColor)
        self.bottom.pack(fill=X)

        self.top_image = PhotoImage(file='Images/Logo.png')
        Label(self.top, image=self.top_image).place(x=-1, y=-1)

        Label(self.bottom, text="Current Version:", bg=self.bottomColor).place(x = 5, y = 15)
        ttk.Entry(self.bottom).place(x = 7, y = 35)

        Label(self.bottom, text="New Version:", bg=self.bottomColor).place(x = 150, y = 15)
        ttk.Entry(self.bottom).place(x = 153, y = 35)

        Button(self.bottom, text = "Get Existing Rules ..").place(x = 5, y = 65)

        self.Lb1 = Listbox(self.bottom).place(x = 5, y = 140)


    def updateListBox(self):
        pass
Reply
#2
you are missing a pack command for self.Lb1
Reply
#3
I tried using the .pack() method, but I still can't get the .insert() to work (Usually the methods associated with the Listbox comes up after I type variableName.). I can, however, do this in my main.py file without any issue. I am guessing this is because I define root = Tk() and then pass that to my Application class.

Is my other class not inheriting the Tk()?
Reply
#4
I don't see anywhere in your code where one class creates an instance of the other.
in addition, the module containing the class must be imported.
-- Edit --
I see here:
    def search(self):
        S = Search.Search()
but still no import, and this is not the proper way to create the instance of search as a new instance will be created every time search is called
Reply
#5
Totally forgot to include my imports in the original post which is below:

# Misc & load functions from other file
import pyodbc
import AddTableAndFunction, Search
import RatingRule
What would be the proper way to create an instance of my Search class?
Reply
#6
instantiate in the __init__ clause of 1st program (you never specified name):
from tkinter import *
from tkinter import ttk
from Search import Search
 
class Application(object):
    def __init__(self, master):
        self.search = Search()
but you also need to separate the __init__ stuff from
procedure. create a method (def) (in Search.py) for the actual search operation
then once instantiated as above, to search something use
self.search.new_method_name(attributes) (use whatever you called new method)
Reply
#7
This thread is a bit stale but since I just wasted over an hour on the same issue I feel I should remind all us Tkinter users (Guido help us!) about this gotcha.
self.Lb1 = Listbox(self.bottom).place(x = 5, y = 140)
Does NOT assign self.Lb1 to the Listbox object! It assigns it to the output of the .place() function. Which is "None", so pretty useless. Always do your Geometry Manager stuff (.grid, .pack or .place) on a separate line when you're assigning the object so you don't fall into this trap:
self.Lb1 = Listbox(self.bottom)
self.Lb1.place(x = 5, y = 140)
It means more: Type Type Type
But much less: Smash Smash Smash
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Reply
#8
Quote:Does NOT assign self.Lb1 to the Listbox object! It assigns it to the output of the .place() function. Which is "None"
I find this hard to believe as I have been using tkinter for years and have never seen this.
That being said, I never combine a widget definition and a geometry on the same line but rather like your second snippet.
Reply
#9
Yeah, strange but true: https://stackoverflow.com/questions/2855...x-elegance

It's also the reason why the OP is getting his: AttributeError: 'NoneType' object has no attribute 'insert'
Because on line 34 in his Second Window code he's in-lining the .place() function so now his self.Lb1 object is of type: None.

self.Lb1 = Listbox(self.bottom).place(x = 5, y = 140)
It's bitten me several times since I tend to favor compact, in-lined code.

Quick example code:
from tkinter import * # Just quick example code.  Star imports are not a good idea!
master = Tk()

btn1 = Button(master, text="ONE")
btn1.pack()

btn2 = Button(master, text="TWO").pack()

print(type(btn1))
print(type(btn2))

<class 'tkinter.Button'>
<class 'NoneType'>

Process finished with exit code 0  
"So, brave knights, if you do doubt your courage or your strength, come no further, for death awaits you all with nasty, big, pointy teeth!" - Tim the Enchanter
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Interaction between Matplotlib window, Python prompt and TKinter window NorbertMoussy 3 341 Mar-17-2024, 09:37 AM
Last Post: deanhystad
  make widgets disappear from tkinter jacksfrustration 12 926 Feb-06-2024, 03:58 PM
Last Post: deanhystad
  Tkinter multiple windows in the same window tomro91 1 785 Oct-30-2023, 02:59 PM
Last Post: Larz60+
  Centering and adding a push button to a grid window, TKinter Edward_ 15 4,371 May-25-2023, 07:37 PM
Last Post: deanhystad
  [Tkinter] Open tkinter colorchooser at toplevel (so I can select/focus on either window) tabreturn 4 1,830 Jul-06-2022, 01:03 PM
Last Post: deanhystad
  [Tkinter] Background inactivity timer when tkinter window is not active DBox 4 2,861 Apr-16-2022, 04:04 PM
Last Post: DBox
  why my list changes to a string as I move to another window in tkinter? pymn 4 2,546 Feb-17-2022, 07:02 AM
Last Post: pymn
  [Tkinter] Tkinter Window Has no Title Bar gw1500se 4 2,795 Nov-07-2021, 05:14 PM
Last Post: gw1500se
  .get() from generated Entry widgets in tkinter snakes 4 4,152 May-03-2021, 11:26 PM
Last Post: snakes
  "tkinter.TclError: NULL main window" Rama02 1 5,781 Feb-04-2021, 06:45 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020