0

I have a program with multiple tabs done across multiple files, with one file for each which I got from here and slightly manipulated it, as it wasn't working into:

main.py

import tkinter as tk
from tkinter import ttk

from tab1 import *
from tab2 import *    

class MainApplication(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)

notebook = ttk.Notebook(parent)

Typ1frame = Typ1(notebook)
Typ2frame = Typ2(notebook)

notebook.add(Typ1frame, text='TAB1')
notebook.add(Typ2frame, text='TAB2')
notebook.pack()

if __name__ == "__main__":
    root = tk.Tk()
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

tab1.py

import tkinter as tk
from tkinter import ttk

class Typ1(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)
    shell_frame=tk.LabelFrame(self, text="Sample Label Frame", padx=5,pady=5)
    shell_frame.grid(row=0,column=0,padx=5,pady=5)

tab2.py

import tkinter as tk
from tkinter import ttk

class Typ2(tk.Frame):
  def __init__(self, parent, *args, **kwargs):
    tk.Frame.__init__(self, parent, *args, **kwargs)
    shell_frame=tk.LabelFrame(self, text="Sample Label Frame", padx=5,pady=5)
    shell_frame.grid(row=0,column=0,padx=5,pady=5)

Now what I want to do with this program is have one login like page, once the user logs in it will change the frame on the same page and then show the program as seen above with tabs. I have tried looking at other pieces of code where they have multiple frames and putting it into my code, but every time I have errors with grid and pack ect., blank boxes or the windows being separate.

If possible could the login page be its own file.

How would I do this, or could you give me clues on how to figure this out myself?

Thanks in advance.

HelloAlll
  • 13
  • 1
  • 6

1 Answers1

0

Turns out your problem is a simple matter of size. The LabelFrame is basically sitting at a zero size because you have not added anything to the frame. So to correct this add width and height to resize the LabelFrame and boom problem solved.

Once you start filling those LabelFrame's with widgets you will no longer need the size formatting.

import tkinter as tk
from tkinter import ttk

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        notebook = ttk.Notebook(parent)

        notebook.add(Typ1(notebook), text='TAB1')
        notebook.add(Typ2(notebook), text='TAB2')
        notebook.pack()

class Typ1(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        shell_frame=tk.LabelFrame(self, text="Sample Label Frame", padx=5, pady=5, width=200, height=200)
        shell_frame.grid(row=0,column=0,padx=5,pady=5)

class Typ2(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        shell_frame=tk.LabelFrame(self, text="Sample Label Frame", padx=5,pady=5, width=200, height=200)
        shell_frame.grid(row=0,column=0,padx=5,pady=5)

if __name__ == "__main__":
    root = tk.Tk()
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

Results:

enter image description here

You could also simply inherit from LabelFrame instead of Frame in your class's to get the same results with less.

Example:

import tkinter as tk
from tkinter import ttk

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        notebook = ttk.Notebook(parent)

        notebook.add(Typ1(notebook), text='TAB1')
        notebook.add(Typ2(notebook), text='TAB2')
        notebook.pack()

class Typ1(tk.LabelFrame):
    def __init__(self, parent, *args, **kwargs):
        tk.LabelFrame.__init__(self, parent, text="Sample Label Frame", padx=5, pady=5, width=200, height=200)
        self.grid(row=0,column=0,padx=5,pady=5)

class Typ2(tk.LabelFrame):
    def __init__(self, parent, *args, **kwargs):
        tk.LabelFrame.__init__(self, parent, text="Sample Label Frame", padx=5, pady=5, width=200, height=200)
        self.grid(row=0,column=0,padx=5,pady=5)

if __name__ == "__main__":
    root = tk.Tk()
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

To answer your comments below here is how you would integrate the frame swapping with a login page.

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self._frame = None
        self.switch_frame(LoginPage)

    def switch_frame(self, frame_class):
        """Destroys current frame and replaces it with a new one."""
        new_frame = frame_class(self)
        if self._frame is not None:
            self._frame.destroy()
        self._frame = new_frame
        self._frame.grid(row=0, column=0)

class LoginPage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        self.master = master
        tk.Label(self, text="Username: ").grid(row=0, column=0)
        tk.Label(self, text="Password: ").grid(row=1, column=0)
        self.un_entry = tk.Entry(self)
        self.un_entry.grid(row=0, column=1)
        self.pw_entry = tk.Entry(self)
        self.pw_entry.grid(row=1, column=1)

        self.pw_entry.bind("<Return>", self.check_login)
        tk.Button(self, text="Login", command=self.check_login).grid(row=2, column=0)


    def check_login(self, event=None):
        if self.un_entry.get() == "Mike" and self.pw_entry.get() == "pass":
            self.master.switch_frame(MainApplication)

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        notebook = ttk.Notebook(parent)

        notebook.add(Typ1(notebook), text='TAB1')
        notebook.add(Typ2(notebook), text='TAB2')
        notebook.grid(row=0, column=0)

class Typ1(tk.LabelFrame):
    def __init__(self, parent, *args, **kwargs):
        tk.LabelFrame.__init__(self, parent, text="Sample Label Frame", padx=5, pady=5, width=200, height=200)
        self.grid(row=0,column=0,padx=5,pady=5)

class Typ2(tk.LabelFrame):
    def __init__(self, parent, *args, **kwargs):
        tk.LabelFrame.__init__(self, parent, text="Sample Label Frame", padx=5, pady=5, width=200, height=200)
        self.grid(row=0,column=0,padx=5,pady=5)

if __name__ == "__main__":
    App().mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • Hey there, thank you so much for an answer. I really appreciate the effort. Could you lead me in the right direction to where I could make my program like [this](https://stackoverflow.com/a/49325719/7150294)? The difference being that the tab widgets would only pop up once the user has passed the login frame (for now it would just be a frame with a change frame button) and also change the actual login frame into what is currently tab1. Thanks in advance. I really appreciate the help. – HelloAlll Oct 18 '18 at 11:02
  • @HelloAlll that should be simple enough. Combining your current code and the code on the linked post should not be difficult. Use their code and make a few small changes. Example `class StartPage(tk.Frame):` should contain your login code and if the user logs in successfully then raise the frame that is your main application. – Mike - SMT Oct 18 '18 at 11:32
  • Thanks, I'll try that when I get home. I really appreciate the help. – HelloAlll Oct 18 '18 at 11:33
  • @HelloAlll I added an example for a login page that will frame swap for your LabelFrame page when user passes the login. – Mike - SMT Oct 18 '18 at 11:46
  • Thank you, I got the program working and now I'm managing the geomtery. One small problem with the code however, when logging in the enter button works but clicking the login button with your mouse yeilds `File "tkinter\__init__.py", line 1702, in __call__ return self.func(*args) TypeError: check_login() missing 1 required positional argument: 'event'`, any recommondations on how to fix this? – HelloAlll Oct 18 '18 at 16:21
  • @HelloAlll Sorry about that, fixed now. The event argument needs to be `event=None` and not just event. My updated example should work now. – Mike - SMT Oct 18 '18 at 16:23
  • Thank you so much! It works perfectly. I really appreciate the help. Tkinter is really confusing for me and your help means a lot. – HelloAlll Oct 18 '18 at 16:24
  • @HelloAlll it can be at first. Once you have worked with it enough you will find it makes more and more sense as you go. I know I had several "aha" moments while learning about tkinter. – Mike - SMT Oct 18 '18 at 16:25