CustomTkinter icon indicating copy to clipboard operation
CustomTkinter copied to clipboard

Why are the grids different?

Open svenakela opened this issue 3 months ago • 4 comments

I have this code in a class that generates a frame for each mp3 file in a list. These frames are added to a scrollable frame.


class Playable(CTkFrame):
    def __init__(self, master:any, controller:UiController, pm:PlayableMeta):
        super().__init__(master)
        self.pm = pm
        self.controller = controller
        self.grid_rowconfigure((0, 1), weight=1)
        self.columnconfigure(index=0, weight=1)
        self.columnconfigure(index=1, weight=5)
        self.columnconfigure(index=2, weight=1)

        self.lbl_title = CTkLabel(self,
                                 text=pm.title,
                                 font=("Arial", 28), anchor="nw")
        self.lbl_artist = CTkLabel(self,
                                 text=pm.artist,
                                 font=("Arial", 16), anchor="nw")
        self.lbl_length = CTkLabel(self,
                                 text="00:00.000",
                                 font=("Arial", 16), bg_color="#228B22", anchor="e", padx=5, pady=5)
        self.lbl_start  = CTkLabel(self,
                                 text="00:00.000",
                                 font=("Arial", 16), bg_color="#444", text_color="#999", anchor="e", padx=5, pady=5)

        if pm.start > 0:
            self.lbl_start.configure(bg_color="#FF6347", text_color="white")

        PositionStuff.full_sticky_mid_pad(self.lbl_title,  row=0, col=1 )
        PositionStuff.full_sticky_mid_pad(self.lbl_artist, row=1, col=1)
        PositionStuff.full_sticky_mid_pad(self.lbl_length, row=0, col=2 )
        PositionStuff.full_sticky_mid_pad(self.lbl_start,  row=1, col=2 )


class PositionStuff:

    @staticmethod
    def full_sticky(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew", padx=10, pady=10)

    @staticmethod
    def full_sticky_mid_pad(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)

    @staticmethod
    def full_sticky_no_pad(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew")

When I run this code with an example of two mp3 files, the labels and titles are rendered in different positions:

Image

In the bottom frame the title is shifted to the left and the labels are shorter. I am confused, as of why? The text is more or less the same length.

If I add the hint I've found on the Internettz:

self.grid_propagate(False)

This happens:

Image

...which is absolutely not want I expected. Is there a way to enforce the grid to be "fixed" in width and height?

svenakela avatar Nov 06 '25 14:11 svenakela

@svenakela Could you please have s sample reproducible code that we can run on our machine?

dipeshSam avatar Nov 08 '25 08:11 dipeshSam

import customtkinter
from customtkinter import CTkLabel, CTkFrame
from dataclasses import dataclass

@dataclass
class Metadata:
    title: str
    artist: str
    length: str
    start: str


class Playable(CTkFrame):
    def __init__(self, master:any, metadata:Metadata):
        super().__init__(master)

        self.grid_rowconfigure((0, 1), weight=1)
        self.columnconfigure(index=0, weight=1)
        self.columnconfigure(index=1, weight=5)
        self.columnconfigure(index=2, weight=1)

        self.lbl_title = CTkLabel(self,
                                  text=metadata.title,
                                  font=("Arial", 28), bg_color="Purple", anchor="nw")
        self.lbl_artist = CTkLabel(self,
                                   text=metadata.artist,
                                   font=("Arial", 16), anchor="nw")
        self.lbl_length = CTkLabel(self,
                                 text=metadata.length,
                                 font=("Arial", 16), bg_color="green", anchor="e", padx=5, pady=5)
        self.lbl_start  = CTkLabel(self,
                                 text=metadata.start,
                                 font=("Arial", 16), bg_color="#444", text_color="#999", anchor="e", padx=5, pady=5)

        self.full_sticky_mid_pad(self.lbl_title,  row=0, col=1 )
        self.full_sticky_mid_pad(self.lbl_artist, row=1, col=1)
        self.full_sticky_mid_pad(self.lbl_length, row=0, col=2 )
        self.full_sticky_mid_pad(self.lbl_start,  row=1, col=2 )

    @staticmethod
    def full_sticky_mid_pad(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)

def main():

    def full_sticky_mid_pad(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)

    ctk = customtkinter.CTk()
    ctk.title("Align Test")
    ctk.geometry("1000x400")

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

    frame = CTkFrame(master=ctk)
    frame.grid_columnconfigure(0, weight=1)
    frame.grid_rowconfigure(0, weight=0)
    frame.grid_rowconfigure(1, weight=0)
    frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)

    # First frame
    m1 = Metadata(title = "Yadee ho hoo", artist = "Mr Bonkers", length = "04:31.003", start  = "00:00.000")
    p1 = Playable(frame, m1)
    p1.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)

    # Second frame
    m1 = Metadata(title = "Balvinore/Dumbledore", artist = "In da getto", length = "03:21.015", start  = "00:51.000")
    p1 = Playable(frame, m1)
    p1.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)

    ctk.mainloop()


if __name__ == "__main__":
    main()
Image

svenakela avatar Nov 08 '25 13:11 svenakela

Updates:

  • I think the first element should be placed on (0, 0).
  • Set proper weightage for each cell.
  • Use fg_color instead of bg_color so that you can use radius also.
  • You can use internal padding to beautify your text.

Revised version of your code:


import customtkinter
from customtkinter import CTkLabel, CTkFrame
from dataclasses import dataclass

@dataclass
class Metadata:
    title: str
    artist: str
    length: str
    start: str


class Playable(CTkFrame):
    def __init__(self, master:any, metadata:Metadata):
        super().__init__(master)

        self.grid_rowconfigure((0, 1, 2, 3), weight=1)
        self.grid_columnconfigure(0, weight=1)

        self.lbl_title = CTkLabel(self, corner_radius=5,
                                  text=metadata.title, padx=10,                                     # Use internal padding for text.
                                  font=("Arial", 28), fg_color="Purple", anchor="nw")
        self.lbl_artist = CTkLabel(self, padx=10,
                                   text=metadata.artist,
                                   font=("Arial", 16), anchor="nw")
        
        self.lbl_length = CTkLabel(self, corner_radius=5,
                                 text=metadata.length,
                                 font=("Arial", 16), fg_color="green", anchor="e", padx=20, pady=5)
        self.lbl_start  = CTkLabel(self, corner_radius=5,
                                 text=metadata.start,
                                 font=("Arial", 16), bg_color="#444", text_color="#999", anchor="e", padx=20, pady=5)

        self.full_sticky_mid_pad(self.lbl_title,  row=0, col=0)
        self.full_sticky_mid_pad(self.lbl_artist, row=1, col=0)

        self.full_sticky_mid_pad(self.lbl_length, row=0, col=1)
        self.full_sticky_mid_pad(self.lbl_start,  row=1, col=1)

    @staticmethod
    def full_sticky_mid_pad(panel, row=0, col=0, padding: tuple = (5, 5)):
        return panel.grid(row=row, column=col, sticky="nsew", padx=padding[0], pady=padding[1])

def main():

    def full_sticky_mid_pad(panel, row=0, col=0):
        return panel.grid(row=row, column=col, sticky="nsew", padx=5, pady=5)

    ctk = customtkinter.CTk()
    ctk.title("Align Test")
    ctk.geometry("1000x400")

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

    frame = CTkFrame(master=ctk)
    frame.grid_columnconfigure(0, weight=1)
    frame.grid_rowconfigure(0, weight=0)
    frame.grid_rowconfigure(1, weight=0)
    frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=10)

    # First frame
    m1 = Metadata(title = "Yadee ho hoo", artist = "Mr Bonkers", length = "04:31.003", start  = "00:00.000")
    p1 = Playable(frame, m1)
    p1.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)

    # Second frame
    m2 = Metadata(title = "Balvinore/Dumbledore", artist = "In da getto", length = "03:21.015", start  = "00:51.000")
    p2 = Playable(frame, m2)
    p2.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)

    ctk.mainloop()


if __name__ == "__main__":
    main()

Output: Screenshot 2025-11-09 114641.png

dipeshSam avatar Nov 09 '25 06:11 dipeshSam

Wait what, this doesn't make sense at all. Even though I agree with your statement Set proper weightage for each cell, it is contradicted by the code you provided.

You are setting cell weight for four rows and one column:

        self.grid_rowconfigure((0, 1, 2, 3), weight=1)
        self.grid_columnconfigure(0, weight=1)

But later the code is using two rows and two columns:

        self.full_sticky_mid_pad(self.lbl_title,  row=0, col=0)
        self.full_sticky_mid_pad(self.lbl_artist, row=1, col=0)

        self.full_sticky_mid_pad(self.lbl_length, row=0, col=1)
        self.full_sticky_mid_pad(self.lbl_start,  row=1, col=1)

In my example code the 0 column is empty on purpose. It is later propagated with icons but it doesn't help to describe the alignment problem. 😃

svenakela avatar Nov 09 '25 10:11 svenakela

Use the 'uniform' property

Schnieker avatar Dec 15 '25 12:12 Schnieker

Unfortunately the UI became too slow with all the UI objects. The project has migrated to Qt.

svenakela avatar Dec 15 '25 22:12 svenakela