Duplicate Frames Created When Calling a Function in a Tkinter Application

1.5k views Asked by At

So this is my first Python GUI project utilizing tkinter. I come from a background in R.

I decided after a review of the documentation to create a class to handle the bulk of the work. The problem appears with my incrementer functions fwd() and bck(). If I do not call these functions in the following chunk of code:

class App:
def __init__(self, master):
    ....
    self.total = 2
    self.fwd()
    self.bck()

The output of the entire code is an empty tkinter frame.

On the other hand, if I do call them, the fwd() function works as one would expect, but every time I click the back button (command = bck()), a new and identical GUI will be attached directly to the bottom of my current GUI. If I click the back button again, another GUI will pop up behind the current GUI.

from tkinter import *
from tkinter import font
from tkinter import filedialog

class App: #I'm not typing what goes in this class, this way I can avoid issues with App(Frame), etc. DUCKTYPE!
def __init__(self, master):
    self.frame = Frame(master)
    self.frame.pack()
    self.master = master
    master.title("PyCCI Caste")
    self.total = 2
    self.fwd() #Need to call these at the beginning otherwise the window is minimized??? No idea why.
    self.bck() #The back button creates a duplicate window...

## +Incrementer
def fwd(self):
    self.total += 1
    print(self.total)

## -Incrementer THIS CREATES A SECOND PANED WINDOW, WHY?!
def bck(self):
    self.total += -1
    if self.total < 3:
        self.total = 2
    print(self.total)


#Body
    self.k1 = PanedWindow(self.frame, #Note: if this is not self.frame, the error: 'App' object has no attribute 'tk' is thrown
                          height=500,
                          width=750,
                          orient = VERTICAL)
    self.k1.pack(fill=BOTH, expand = 1)
    self.titlefont = font.Font(size = 12,
                               weight = 'bold')
    self.boldfont = font.Font(size=8,
                              weight = 'bold')
    self.textfont = font.Font(family = 'Arial',
                              size = 10)

#Title
    self.title = PanedWindow(self.k1)
    self.k1.add(self.title, padx = 10, pady = 10)
    Label(self.title, text = "Chronic Critically Ill Patient GUI",
          font = self.titlefont,
          fg="darkslateblue").pack()

#Top row open csv window & button
    self.k2 = PanedWindow(self.k1)
    self.k1.add(self.k2)
    self.openbutton = Button(self.k2,
                             text = "Open CSV")#, command = openfile())
    self.openbutton.pack(side = LEFT,
                         padx = 30)

#Panes below buttons
    self.k3 = PanedWindow(self.k1)
    self.k1.add(self.k3)
    self.leftpane = PanedWindow(self.k3)
    self.k3.add(self.leftpane,
                width = 400,
                padx = 30,
                pady = 25,
                stretch = "first")
    self.separator = PanedWindow(self.k3,
                                 relief = SUNKEN)
    self.k3.add(self.separator,
                width=2,
                padx=1,
                pady=20)
    self.rightpane = PanedWindow(self.k3)
    self.k3.add(self.rightpane,
                width = 220,
                padx = 10,
                pady = 25,
                stretch = "never")

#Left pane patient note text frame doo-diddly
    self.ptframe = LabelFrame(self.leftpane,
                              text = "Medical Record",
                              font = self.boldfont,
                              padx = 0,
                              pady=0,
                              borderwidth = 0)
    self.ptframe.pack()
    Label(self.ptframe,
          text = "patient # of ##").pack()

#Incrementer buttons
    self.buttonframe = Frame(self.ptframe)
    self.buttonframe.pack()
    self.buttonframe.place(relx=0.97, anchor = NE)
    #Back Button
    self.button1 = Button(self.buttonframe, text = 'Back', width = 6, command = self.bck)
    self.button1.grid(row = 0, column = 0, padx = 2, pady = 2)
    #Next Button
    self.button2 = Button(self.buttonframe, text = 'Next', width = 6, command = self.fwd)
    self.button2.grid(row = 0, column = 2, padx = 2, pady = 2)

#Scrollbar!
    self.ptscroll = Scrollbar(self.ptframe)
    self.ptscroll.pack(side = RIGHT, fill = Y)
    self.pttext = Text(self.ptframe,
                       height=300,
                       width=400,
                       wrap=WORD,
                       font=self.textfont,
                       spacing1=2,
                       spacing2=2,
                       spacing3=3,
                       padx=15,
                       pady=15)
    self.pttext.pack()
    self.ptscroll.config(command=self.pttext.yview)
    self.pttext.config(yscrollcommand=self.ptscroll.set)

#Checkbuttons
    self.checkframe = LabelFrame(self.rightpane, text="Indicators",
                                 font=self.boldfont,
                                 padx = 10,
                                 pady = 10,
                                 borderwidth=0)
    self.checkframe.pack()
    self.check1 = Checkbutton(self.checkframe, text="Non-Adherence")
    self.check1.grid(row = 1,
                     column = 0,
                     sticky = W)

root = Tk()
app = App(root) ## apply the class "App" to Tk()

### Menu stuff does not need to be part of the class
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="Open CSV")#, command=openfile)
menubar.add_cascade(label="File", menu=filemenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="About")#, command=about)
menubar.add_cascade(label="Help", menu=helpmenu)
root.config(menu=menubar)
root.mainloop()

What do you folks think? If I'm missing any pertinent information here, please let me know. The difficulty I'm having is that I don't know what I don't know about Python/Tkinter yet.

Thanks, I really appreciate any insight and direction.

Solved (thanks Bryan Oakley & TigerhawkT3): Due to Python's use of indentation as part of its syntax, I had created a function bck() which, when called, includes the code for the entirety of the rest of the GUI. To solve this problem after it was pointed out, I drew heavily from: Python def function: How do you specify the end of the function?

1

There are 1 answers

1
Bryan Oakley On BEST ANSWER

You appear you have a simple indentation error. It seems like you intend for bck to have four lines of code, but because almost all of the remaining code is indented the same, it is all considered to be part of bck.