Home > Software engineering >  Clearing a tkinter root.subform from within a separate function
Clearing a tkinter root.subform from within a separate function

Time:01-02

I have several larger tkinter / python program which I would like to incorporate into one program which would clear a frame when another program is called; each program currently being inside a function (I probably should use classes eventually when I understand them) and each of these function being displayed on a form being cleared of widgets from the previous if any do exist.

The code below is just a small trial for me to understand how to do this, but it's not working.

When I invoke the widget.destroy() function, it removes the frame (DisplayFrame) and does not clear the widgets inside it and hence not displaying the new widgets.

here is the current trial code:

#!/usr/bin/env python3

import tkinter as tk
from tkinter import *
from tkinter import ttk
#import pandas as pd
import MultiTempsP3
import datetime, time

from tkinter import messagebox
import sqlite3
from tkinter import colorchooser
from configparser import ConfigParser

import os
import csv

if os.environ.get('DISPLAY','') == "":
    print('no display found.Using :0.0')
    os.environ.__setitem__('DISPLAY',':0.0')

root = tk.Tk()
root.title("Kombucha Program")
root.geometry("1400x800")
root.minsize(width=900, height=600)
    #root.maxsize(width=1400, height = 900)
root.grid_rowconfigure(3, weight=1)
root.grid_columnconfigure(2, weight=1)
root.configure( bg = '#000080' )

DisplayFrame = tk.Frame(root, width=1200, height = 630, bg = 'yellow')       #0059b3')
DisplayFrame.grid(column=0,row=1, sticky = N, in_ = root)

rightFrame = tk.Frame(root, width = 120, height = 390, bg = 'white') # #000080
rightFrame.grid(column = 1, row = 0, pady = 10, padx = 10)

lblFrame = tk.Frame(root, height = 70, width = 670, bg = 'black')
lblFrame.grid(column = 0, row = 0, sticky =N, in_ = root)

##'W' stands for West = WrightFrmae (west fframe on the right of screen
#WrightFrame = tk.Frame(rightFrame, width = 70, height = 300, bg = 'green') #  #000080
#WrightFrame.grid(column = 0, row = 1)

WidgetFrame = tk.Frame(root, height = 300, width = 120, bg = 'red') # #000080
WidgetFrame.grid(column=0,row=2, pady = 30)

fromTemp =  MultiTempsP3.temps("65cd6bd")
lblTemp = Label(rightFrame, text=fromTemp).grid(row=1,column=0,pady=0 )
#lblTemp.pack()

def clearDisplayFrame():
    for widgets in DisplayFrame.winfo_children():
        widgets.destroy()
        
###***### - This section is in the right top little frame = rightFrame
state = "yes" ## delete this row and use below state=GPIO when on an RPi
#state = GPIO.input(17)
if state:
    state_17="GPIO_17 (HeatPad) is On "
else:
    state_17="GPIO_17 (HeatPad) is Off "
lblHeatPad = Label(rightFrame, text=state).grid(row=3,column=0,pady=0 ) #shows as text in the window
#lblHeatPad.pack() #organizes widgets in blocks before placing them in the parent.          
###***### End of rightFrame widgets



def func_quit():
    root.destroy()



def openData():
    clearDisplayFrame()
    print("I am inside openData()")
    lbltrial=tk.Label(DisplayFrame,text="trial").grid(row=3, column=2)
    
def func_Temps():
    clearDisplayFrame()
    print("I am inside func_Temps()")
    
    #DisplayFrame = tk.Frame(root, width=1200, height = 630, bg = 'yellow')       #0059b3')
    #DisplayFrame.grid(column=0,row=1, sticky = N, in_ = root)    
    lblSomething = tk.Label(DisplayFrame, text = "Open Temps").grid(row=2,column=2)
    

###***### This section is top of left = lblFrame

exitButton = tk.Button(lblFrame, text="Quit the Program",  width = 12, command=root.destroy, bg= "magenta")
exitButton.grid(row = 0, column = 0, columnspan = 1, pady = 5, padx = 5)
dataButton = Button(lblFrame, text="Open Dates Window", command=openData).grid(row=0, column=1)  ## the open refers to the above function
tempsButton= Button(lblFrame, text="Open Temps Info", command=func_Temps).grid(row=0, column=2)
###***### End of top left widget in lblFrame


mainloop()

CodePudding user response:

As an answer, here is an approach that uses 2 frame and switches between them in the click of the switch. This is the way usually switching between frame is implemented in procedural programming, AFAIK:

from tkinter import *

root = Tk()

def change(frame):
    frame.tkraise() # Raising the passed frame

window1 = Frame(root)
window2 = Frame(root)

window1.grid(row=0,column=0) # Grid in the same location so one will cover/hide the other
window2.grid(row=0,column=0)

# Contents inside your frame...
Label(window1,text='This is page 1',font=(0,21)).pack()
Label(window2,text='This is page 2',font=(0,21)).pack()

# Buttons to switch between frame by passing the frame as an argument
Button(root,text='Page 1',command=lambda: change(window1)).grid(row=1,column=0,stick='w')
Button(root,text='Page 2',command=lambda: change(window2)).grid(row=1,column=0,stick='e')

root.mainloop()

So instead of destroying all the items inside your frame, you should just raise the other frame, as destroyed widgets cannot be brought back.

  • Related