pythontkinterpython-imaging-libraryflicker

Python: Tkinter frame appearing/disappearing and not showing children widgets


I am making a game to test my skills, and i created a frame that should show a few more frames containing labels with text and images. For some reason, the main frame appears and disappears by itself, sometimes staying on screen for a few seconds, sometimes flickering. No widgets seem to appear inside the frame.

I added some debug prints and it seems that all images are loaded properly. The program doesn't stop, it keeps working but, as i said, that one frame seems to flicker and disappear.

Here's the code of the function that is called to show the problematic frame:

def show_party():
    global root, screenw, button_set, collection_page, selected_party_member

    try:
        screenw["PARTY_GRID"].destroy()
        del screenw["PARTY_GRID"]
    except: pass

    screenw["PARTY_GRID"] = Frame(
        root,
        bg = "#050505",
        width = 450,
        height = 128 * 6,
    )
    screenw["PARTY_GRID"].place(x = 100, y = 150)

    n = 0

    for party_slot in player_account.party:
        n += 1
        screenw[f"PARTY_FRAME_NO{n}"] = Frame(
            screenw["PARTY_GRID"],
            bg = "#FFFFFF",
        )

        screenw[f"PARTY_FRAME_NO{n}"].grid(row = n, column = 0)

        print(f"PARTY SLOT NO. {n}: {party_slot}")

        if party_slot[0] != None:
            pokeicon = POKEMON_ICONS[party_slot[0].id]
        else:
            pokeicon = IMAGE_UNKNOWN

        print(f"POKEICON NO. {n}: {pokeicon}")

        screenw[f"PARTY_NO{n}_ICON"] = Button(
            screenw[f"PARTY_FRAME_NO{n}"],
            bg = "#050505",
            image = pokeicon,
            border = 0,
            borderwidth = 0,
        ) #

        print(f"ICON LOADED!")

        screenw[f"PARTY_NO{n}_ICON"].place(x = 0, y = 0)

        print(f"ICON PLACED!")

        if party_slot[0] != None:
            screenw[f"PARTY_NO{n}_NICKNAME"] = Label(
                screenw[f"PARTY_FRAME_NO{n}"],
                bg = "#050505",
                fg = "#FFFFFF",
                font = ("Minecraft", 15),
                text = f"{party_slot[0].nickname}",
            )

            screenw[f"PARTY_NO{n}_NICKNAME"].place(x = 132, y = 0)
            screenw[f"PARTY_NO{n}_LEVEL"] = Label(
                screenw[f"PARTY_FRAME_NO{n}"],
                bg = "#050505",
                fg = "#FFFFFF",
                font = ("Minecraft", 10),
                text = f"Level {party_slot[0].level}",
            )

            screenw[f"PARTY_NO{n}_LEVEL"].place(x = 132, y = 20)

I am using Python 3.10.11.


Solution

  • Note that putting widgets into a frame using .place() does not adjust the size of the parent frame, so the parent frame will be of size 1x1 in pixel by default.

    You need to specify the size of the parent frame that is large enough to see all the child widgets:

    for party_slot in player_account.party:
        n += 1
        screenw[f"PARTY_FRAME_NO{n}"] = Frame(
            screenw["PARTY_GRID"],
            bg = "#FFFFFF",
            width = 200,   # adjust this value to the desired width
            height = 200,  # adjust this value to the desired height
        )
        ...
    

    Or use .grid() or .pack() to put those child widgets.