Conor Egan
Conor Egan

Reputation: 469

Python tkinter issues aligning

I'm creating an application to try and learn python and tkinter. The problem I'm having is I can't seem to align the entries and labels as I want them. I would like to arrange them like this:

labelUsername entryUsername
labelPassword entryPassword

However, it's currently like this:

labelUsername
entryUsername
labelPassword
entryPassword

Here is my code:

import tkinter as tk
from tkinter import ttk

TITLE_FONT = ("Verdana", 12)
NORMAL_FONT = ("Verdana", 8)

class CCTV(tk.Tk):

    def __init__(self, *args, **kwargs):

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

        container = tk.Frame(self)
        container.pack()
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (LoginPage, PageOne):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(column=0, row=0, sticky="nsew")

        self.show_frame(LoginPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()


class LoginPage(tk.Frame):

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

        label = ttk.Label(self, text="Login Page", font=TITLE_FONT)
        label.pack(padx=20, pady=20)

        labelUsername = ttk.Label(self, text="Username", font=NORMAL_FONT)
        labelUsername.grid(row=0, sticky="w")
        labelUsername.pack()

        entryUsername = ttk.Entry(self, font=NORMAL_FONT)
        entryUsername.grid(column=1, row=0)
        entryUsername.pack()

        labelPassword = ttk.Label(self, text="Password", font=NORMAL_FONT)
        labelPassword.grid(row=1, sticky="w")
        labelPassword.pack()

        entryPassword = ttk.Entry(self, show = "*", font=NORMAL_FONT)
        entryPassword.grid(column=1, row=1)
        entryPassword.pack()

        loginButton = ttk.Button(self, text="Login", command=lambda: controller.show_frame(PageOne))
        loginButton.grid()
        loginButton.pack()


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page One", font=TITLE_FONT)
        label.pack(padx=20, pady=20)

        button1 = tk.Button(self, text="Back to home", command=lambda: controller.show_frame(LoginPage))
        button1.pack()


app = CCTV()
app.geometry("800x600")
app.mainloop()

If you're wondering why I have lots of code for such a simple program, it's so I can change the frame which is being viewed so I can have multiple frames without creating new windows. Any help would be highly appreciated.

Upvotes: 0

Views: 160

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 386342

If you want to lay widgets out in a grid, use grid. You're using grid, but then you're throwing away the effects of grid by calling pack. You must use one or the other within a frame, not both.

Pro tip: layout is easier when you group your layout code together rather than interlacing it with widget creation. By putting your layout code together in a block it becomes much easier to see the relationship of widgets.

The following examples shows how to get two rows and two columns for the entry widgets and their labels:

class LoginPage(tk.Frame):

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

        label = ttk.Label(self, text="Login Page", font=TITLE_FONT)
        labelUsername = ttk.Label(self, text="Username", font=NORMAL_FONT)
        entryUsername = ttk.Entry(self, font=NORMAL_FONT)
        labelPassword = ttk.Label(self, text="Password", font=NORMAL_FONT)
        entryPassword = ttk.Entry(self, show = "*", font=NORMAL_FONT)
        loginButton = ttk.Button(self, text="Login", command=lambda: controller.show_frame(PageOne))

        label.grid(row=0, columnspan=2, pady=10)
        labelUsername.grid(row=1, column=0, sticky="w")
        entryUsername.grid(row=1, column=1)
        labelPassword.grid(row=2, column=0, sticky="w")
        entryPassword.grid(row=2, column=1)
        loginButton.grid()

Upvotes: 1

Related Questions