1

I am trying to make a Tkinter GUI that takes Excel documents, reads them, and exports them to the window. The issue is when I changed the code to below to incorporate class structure, I cannot make the GUI load properly anymore.

import tkinter as tk
from tkinter.filedialog import askopenfilename

def NewFile():
    print("New File!")
def OpenFile():
    name = askopenfilename()
    print(name)
def About():
    print("About works")
def deletelist():
    listbox.delete(0, END)

class MainApplication(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.master = master
        self.frame = tk.Frame(self.master)

        self.load = tk.Button(self.frame, text = "Load XLSX File", command = OpenFile)
        self.load.grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'w')

        self.ckframe = tk.LabelFrame(self.frame, text="Currency Selections")
        self.ckframe.grid(row = 1, column = 0, padx = 5, pady = 5, stick = 'nesw')
        self.prochk = tk.Checkbutton(self.ckframe, text = '1 Currency').grid(row = 1, column = 0, columnspan = 2, sticky = 'w')
        self.msnchk = tk.Checkbutton(self.ckframe, text = '2 Currency').grid(row = 1, column = 2, columnspan = 2, sticky = 'w')
        self.nightschk = tk.Checkbutton(self.ckframe, text = '3 Currency').grid(row = 1, column = 4, columnspan = 2, sticky = 'w')
        self.semichk = tk.Checkbutton(self.ckframe, text = '4 Currency').grid(row = 2, column = 0, columnspan = 2, sticky = 'w')
        self.instqualCRchk = tk.Checkbutton(self.ckframe, text = '5 Currency').grid(row = 2, column = 2, columnspan = 2, sticky = 'w')
        self.msnCRchk = tk.Checkbutton(self.ckframe, text = '6 Currency').grid(row = 2, column = 4, columnspan = 2, sticky = 'w')

        self.listbox = tk.Listbox(self.frame, width = 83)
        self.listbox.grid(row = 3, column = 0, columnspan = 1, sticky = 'w') # Fix width size function
        self.listbox.insert(1, 'Test1')
        self.listbox.insert(0, 'Test2')
        self.save = tk.Button(self.frame, text = "Save").grid(row = 8, column = 0, padx = 5, pady = 5, stick = 'e')
        self.delete = tk.Button(self.frame, text = "Delete", command = deletelist).grid(row = 8, column = 0, padx = 45, pady = 5, stick = 'e')

if __name__ == '__main__':
    root = tk.Tk()
    MainApplication(root)
    root.mainloop()

I searched a lot trying to find a solution to using classes with tkinter GUI and the grid system but I mostly found ways to make GUIs with pack() solution.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • Read [AttributeError: NoneType object has no attribute](https://stackoverflow.com/a/1101765/7414759) and [Best way to structure a tkinter application?](https://stackoverflow.com/a/17470842/7414759) – stovfl May 29 '20 at 20:08
  • @stovfl: neither of those links are relevant to this question. – Bryan Oakley May 29 '20 at 20:16

1 Answers1

0

The instance of MainApplication is a frame. You never call pack or place or grid on that instance so that frame and all of its children will be invisible.

This frame creates another frame that contains all of the other widgets, self.frame. You never call pack, place, or grid on it either, so it and all of its children will be invisible.

Since the widgets are in a frame that is invisible, and that frame itself is invisible, none of the other widgets will be visible.

The first thing to do is to get rid of self.frame. Remove the line that creates it, and everywhere you reference self.frame, replace it with self. Since self in this context is already a frame it makes no sense to create another frame inside.

Next, you need to add the instance of MainApplication to the window. Since it's the only widget directly in the root window, pack is the simplest choice.

root = tk.Tk()
app = = MainApplication(root)
app.pack(fill="both", expand=True)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • That works but messes up the formatting a little bit. I did find that I never defined the frame in `MainApplication` so I added `self.frame.grid(row=0, column=0, sticky='nsew')` under `self.frame = tk.Frame(self.master)` and that worked as well. How will this effect my program overall compared to using `pack()`? – Micah Rutherford May 29 '20 at 20:26
  • @MicahRutherford: as long as you remember to call `grid_rowconfigure` and `grid_columnconfigure` to assign weights appropriately, `grid` will work just as well as `pack`. However, if `self.frame` has `self.master` as it's parent, it defeats the purpose of `MainApplication` inheriting from `Frame`. It's a bad practice for a class like this to put widgets in the parent rather than in itself. It destroys encapsulation. – Bryan Oakley May 29 '20 at 20:42
  • Thank you for the quick replies! Makes sense and the program works perfect now after a little tweaking with the rows and columns in the widgets. Actually works better now. – Micah Rutherford May 29 '20 at 20:53