Search code examples
pythonuser-interfacetkintercomputer-science

How do I enable .grid?


I wanted to position in the username and password such that it is next to each other. In order to achieve that I used the grid method but I keep getting an error that says:

_tkinter.TclError: cannot use geometry manager grid inside .!frame.!adminlogin.!frame which already has slaves managed by pack.

Is there a way I can let it use even grid?

import tkinter as tk
from tkinter import font as tkfont
import PIL.Image
from PIL import ImageTk
from tkinter import *
import tkinter.font as font
import sqlite3, hashlib
from datetime import date


class SampleApp(tk.Tk):

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

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        self.geometry ("1024x768")
        container = tk.Frame(self)

        container.pack(fill="both", side= 'top',expand=True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (StartPage, StudentLogin, AdminLogin):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.controller = controller
        frame = tk.Frame(self, width = 1024, height = 768, bg="teal")

        frame.pack(fill="both", expand=True, side="top")
        label = tk.Label(frame, text="WELCOME", font=controller.title_font)
        label.pack(side="top", fill="x", pady=50)

        button1 = tk.Button(frame, text="Admin Login",
                            command=lambda: controller.show_frame("AdminLogin"), width = 50, height=10, font=30, bg='powder blue')
        button2 = tk.Button(frame, text="Student Login",
                            command=lambda: controller.show_frame("StudentLogin"), width=50, height=10, font=30, bg='powder blue')
        button1.pack(pady=10)
        button2.pack(pady=10)


class AdminLogin(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        frame = tk.Frame(self, width = 1024, height = 768, bg='teal')
        frame.pack(fill="both", side ="top", expand=True)
        label = tk.Label(frame, text="Enter username and password to login", font=controller.title_font)
        label.pack(side="top", fill="x", pady=30, padx =10)
        userLabel = tk.Label(frame, text = "Enter Username: ", font=50)

        userLabel.pack(padx=10, pady=10)
        userEntry = tk.Entry(frame)
        userEntry.pack(padx=10, pady=10)

        passwordL = tk.Label(frame, text = "Enter Password: ", font=50)
        passwordL.pack(padx=10, pady=10)
        passEntry = tk.Entry(frame, show="*")
        passEntry.pack(padx=10, pady=10)
        button = tk.Button(frame, text="Back",
                           command=lambda: controller.show_frame("StartPage"), bg='powder blue')
        button.pack()


class StudentLogin(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        frame = tk.Frame(self, width = 1024, height = 768, bg='teal')
        frame.pack(fill="both", side ="top", expand=True)
        label = tk.Label(frame, text="Enter username and password to login", font=controller.title_font)
        label.pack(side="top", fill="x", pady=30, padx =10)
        button = tk.Button(frame, text="Back",
                           command=lambda: controller.show_frame("StartPage"), bg='powder blue')
        button.pack()


if __name__ == "__main__":
    app = SampleApp()


    app.mainloop()

Solution

  • Unfortunately you cannot mix both the pack and grid methods. You have to only pick one, which you will use throughout that master. Pack is easier to use, but with grid you have more control over where your widgets are going to be displayed in the window. (I would have done this as a comment to your post, not an answer, but i do not have enough reputation to do so) I hope this helps :)