Как удалить полигон в tkinter?

#python #tkinter

#python #tkinter

Вопрос:

Я пытаюсь создать базовую игру в Tkinter, которая включает в себя нажатие кнопки «Пуск» и отображение фигуры, которая работает, затем, когда вы нажимаете на фигуру, она удаляется и перемещается в другое случайное место.

Я получаю NameError: name 'square' is not defined , когда пытаюсь его запустить.

 root=Tk()
frame=Frame(root)
can = Canvas(root, width=400, height=400)
can.pack(side=TOP)

def makeShape():
    xpos = random.randint(1, 400)
    ypos = random.randint(1, 400)
    square=can.create_polygon(xpos, ypos, xpos   40, ypos, xpos   40, ypos   40, 
                              xpos, ypos   40, fill="blue")
    can.tag_bind(square,"<Button-1>",deleteShape)

def deleteShape(event):
    can.delete(square)

but1 = Button(frame, text="Start", command=makeShape)
but1.grid(row=1, column=2)

frame.pack(side=BOTTOM)
root.mainloop()
 

Комментарии:

1. Зачем удалять и создавать заново? На холсте есть способы перемещения объекта.

2. @BryanOakley возможно, это было бы проще, но я боролся с перемещением из-за случайных координат

3. Майк: Случайные координаты не должны быть проблемой, потому что при перемещении элемента Canvas все, что вам нужно указать, это суммы для перемещения в направлениях x и y (и тег или идентификатор объекта).).

4. @martineau итак, должен ли я сделать его похожим на приведенный выше код makeShape, но заменить create на move, или это приведет к перемещению фигуры с холста или аналогичной ошибке?

5. Пожалуйста, не вандализируйте свои посты. После того, как вы отправили сообщение, вы лицензировали контент сообществу Stack Overflow в целом ( по лицензии CC BY-SA ). Согласно политике SE, любой вандализм будет отменен.

Ответ №1:

Это потому square , что это локальная переменная внутри makeShape() , поэтому к ней нельзя получить доступ вне функции.

Вместо этого вы можете использовать tags option in create_polygon() . Если вы хотите переместить квадрат при нажатии на него, deleteShape() в этом нет никакой необходимости. Достаточно просто использовать makeShape() :

 from tkinter import *
import random

root=Tk()
frame=Frame(root)
can = Canvas(root, width=400, height=400)
can.pack(side=TOP)

def makeShape():
    # delete existing square
    can.delete("square") 
    # create square at random position
    xpos = random.randint(1, 360)
    ypos = random.randint(1, 360)
    can.create_polygon(xpos, ypos, xpos 40, ypos, xpos 40, ypos 40, xpos, ypos 40,
                       fill="blue", tags="square")
    # call makeShape() when the square is clicked
    can.tag_bind("square", "<Button-1>", lambda e: makeShape())

but1 = Button(frame, text="Start", command=makeShape)
but1.grid(row=1, column=2)

frame.pack(side=BOTTOM)
root.mainloop()
 

Комментарии:

1. @Mike: Это решение лучше в том смысле, что оно не требует использования глобальной переменной (хотя само имя тега, вероятно, следует сделать глобальной константой ).

Ответ №2:

Хотя это не очень хорошая практика, если вы добавите к ней строку global square makeShape() , она будет работать так, как ожидалось.

Это связано с тем, что если имя присваивается в первый раз внутри блока, оно не будет видно родительским или родственным блокам.

Существуют альтернативы, которые считаются лучшими для удобства чтения и более практичными, но мое предложение — это самое быстрое решение вашей проблемы.

Комментарии:

1. Хорошо, спасибо, просто из интереса, что бы вы предложили, чтобы улучшить его читаемость?

2. @Mike: Если вы удалите фигуру, вы не сможете ее переместить (очевидно). Простое создание square глобальной переменной не повлияет на возможность ее перемещения в противном случае.