EvilVolatile
EvilVolatile

Reputation: 3

tkinter - mistake in the layout

In the code below, I want the label on line 34 to go to the top of my canvas, as the label on line 59 does. But it goes to the bottom of my canvas instead, even though I'm using the same code in both places.

Here is my code (with code that causes problems marked with #):

from tkinter import*
from random import*

score = 0

Fenetre = Tk()

def Clavier(event):
    global coords
    global score
    global label

    touche = event.keysym

    if touche == "Up":
        coords = (coords[0], coords[1] - 10)
    elif touche == "Down":
        coords = (coords[0], coords[1] + 10)
    elif touche == "Right":
        coords = (coords[0] + 10, coords[1])
    elif touche == "Left":
        coords = (coords[0] -10, coords[1])

    canvas.coords(eater, coords[0], coords[1], coords[0]+20, coords[1]+20)

    while canvas.bbox(eater) == canvas.bbox(food):
        canvas.delete(food)
        label.destroy()
        global food
        up_score = score
        up_score = up_score + 1
        score = up_score
        label = Label(Fenetre, text = up_score) # line 34
        label.pack()
        X=choice(liste)
        Y=choice(liste)
        food = canvas.create_rectangle(X,Y,X+20,Y+20,fill="grey")

#fond = PhotoImage(file="Moi.gif")

canvas = Canvas(Fenetre, width=189, height=189)
#canvas.create_image(0,0,image=fond,anchor = NW)

coords = (0, 0)

liste_couleur = ["green","white","red","blue","yellow","violet","orange"]
couleur = choice(liste_couleur)
eater = canvas.create_oval(0,0,20,20,fill=couleur)

canvas.focus_set()
canvas.bind("<Key>", Clavier)

liste = [10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170,180]
X = choice(liste)
Y = choice(liste)
food = canvas.create_rectangle(X,Y,X+20,Y+20,fill="grey")

label = Label(Fenetre, text = score) # line 59

label.pack()
canvas.pack()
Fenetre.mainloop()

If it matters, I'm using Python 3.2.

Upvotes: 0

Views: 49

Answers (1)

abarnert
abarnert

Reputation: 365717

The reason the new label doesn't go to the same place as the original label is… well, that's the way the pack geometry manager works: Where something goes depends on what else already exists at the time you pack it. The original label gets packed into an empty space, and then other stuff gets packed after it, so it ends up on top. The new label gets packed into a space that already has that other stuff, so it ends up on the bottom.

You could work around this by just passing the side=BOTTOM argument.

Or you could use a grid layout instead of a pack layout to make sure everything ends up exactly where you want it.

However, I think what you really want here is a lot simpler: instead of repeatedly destroying labels and creating new ones and hoping you can fit them in the same place, just keep the label and change its text.

In other words, instead of this:

    label.destroy()
    # other code
    label = Label(Fenetre, text = up_score) # line 34
    label.pack()

… just do this:

    # other code
    label.config(text=up_score)

Or, maybe even better, assign a StringVar to the Label, and just call set on that StringVar (as demonstrated in the next-to-last pattern in the Label docs in the Tkinter book).

Upvotes: 1

Related Questions