Ernie Peters
Ernie Peters

Reputation: 717

tkraise not hiding 'bottom' frame

I'm struggling with tkraise not hiding the 'bottom' frame in my app. I have two frames, one contains a Listbox and is packed to the left and the other will display options for each item in the listbox and is packed to the right. My problem is that I can see the Future page when I select General and vise versa. I copied and modified it from my working main app but I don't know what I did wrong to break it for this one.

# All settings windows and forms labels are built in here

import tkinter as tk
# from main import WinSize
from tkinter import Listbox, END, ttk


class Settings(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # create frame for listbox and parameters area
        self.list_container = ttk.Frame(self, relief='sunken')
        self.list_container.pack(side='left', fill='y', expand=False)
        self.param_container = ttk.Frame(self)
        self.param_container.pack(side='top', fill='both', expand=True)


        self.options_list = Listbox(self.list_container, selectmode='single')

        for choice in ['General', 'Future']:
            self.options_list.insert(END, choice)


        self.okbutton = ttk.Button(self.param_container, text="OK", command= self.destroy)
        self.okbutton.grid_rowconfigure(0, weight=1)
        self.okbutton.grid_columnconfigure(0, weight=1)
        self.okbutton.grid(row=2, column=2, sticky='nsew')

        # Grid layout for Settings window
        self.options_list.grid(row=0, column=0, sticky='nsew')

        self.list_container.grid_rowconfigure(1, weight=1)
        self.list_container.grid_columnconfigure(1, weight=1)

        self.param_container.grid_rowconfigure(1, weight=1)
        self.param_container.grid_columnconfigure(1, weight=1)

        # create empty TUPLE for future frames
        self.frames = {}
        # generate calls for frames
        for F in (General, Future):
            self.page_name = F.__name__
            self.frame = F(parent=self.param_container, controller=self)
            self.frames[self.page_name] = self.frame

        self.options_list.select_set(0)
        self.options_list.bind("<<ListboxSelect>>", self.onselect)
        self.options_list.event_generate("<<ListboxSelect>>")

    # grab value of listbox selection and call show_frame
    def onselect(self, event):
        self.widget = event.widget
        self.value = self.widget.get(self.widget.curselection())
        print(self.value)
        self.show_frame(self.value)

    # show corresponding frame based on listbox selection
    def show_frame(self, page_name):
        # show a frame for the given page name
        self.frame = self.frames[page_name]
        self.frame.grid(row=0, column=1, sticky='nsew')
        self.frame.tkraise()
        print("Show Frame")


class General(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        self.optiontitle = ttk.Label(parent, text='General')
        self.optiontitle.grid(row=0, column=0, sticky='nsew')
        self.dirlabel = ttk.Label(parent, text='Default Save Directory')
        self.dirlabel.grid(row=1, column=1, sticky='s')


class Future(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        test1 = ttk.Label(self, text='Future')
        test1.pack()


app=Settings()
app.mainloop()

I want to say it may be something to do with my grid layout but it doesn't make sense since the two 'pages' are not coupled (or supposed to be) with each other.

Upvotes: 0

Views: 1092

Answers (2)

Ernie Peters
Ernie Peters

Reputation: 717

I solved this issue through another problem that I was able to work out with some help from others. Refer to this → Frames not stacking on top of each other in tkinter question as it has two great answers which easily allow to incorporate grid_forget() and/or pack_forget() as suggested by @jasonharper.

Upvotes: 1

jasonharper
jasonharper

Reputation: 9597

You aren't doing anything to actually hide the other page; you're just layering the new page on top of it, which isn't going to look right unless they occupy exactly the same screen area.

Even if they did, this still isn't a workable approach, since the widgets in the hidden page are still active. In particular, if it had any Entry or Text fields, they could still have (or gain) keyboard focus, so anything the user types might mysteriously end up in a field they can't even see at the moment.

You should call .grid_forget() on the previous page when showing the new one. Or, perhaps easier, call .grid_forget() on all pages before calling .grid() on the new one (it doesn't hurt to call this on a widget that isn't currently shown).

Upvotes: 0

Related Questions