Home > database >  Moving widgets in Canvas Tkinter
Moving widgets in Canvas Tkinter

Time:11-29

I have a canvas with a little oval in it. It moves throughout the widget using the arrow keys but when it's on the edge of the canvas if I move it beyond that, the oval just disappears.

I want the oval stays on any edge of the canvas no matter if I continue pressing the arrow key corresponding to that edge without disappearing.

This is the code:

from tkinter import *

root = Tk()
root.title("Oval")
root.geometry("800x600")

w = 600
h = 400
x = w//2
y = h//2

my_canvas = Canvas(root, width=w, height=h, bg='black')
my_canvas.pack(pady=20)

my_circle = my_canvas.create_oval(x, y, x 20, y 20, fill='cyan')


def left(event):
    x = -10
    y = 0
    my_canvas.move(my_circle, x, y)


def right(event):
    x = 10
    y = 0
    my_canvas.move(my_circle, x, y)


def up(event):
    x = 0
    y = -10
    my_canvas.move(my_circle, x, y)


def down(event):
    x = 0
    y = 10
    my_canvas.move(my_circle, x, y)



root.bind('<Left>', left)
root.bind('<Right>', right)
root.bind('<Up>', up)
root.bind('<Down>', down)

root.mainloop()

This is what it looks like:

The oval on an edge

And if I continue pressing the key looks like this:

The oval disappearing

CodePudding user response:

You could test the current coordinates and compare them to your canvas size. I created a function to get the current x1, y1, x2, y2 from your oval. This way you have the coordiantes of the borders of your oval.

So all I do is testing if the oval is touching a border.

from tkinter import *

root = Tk()
root.title("Oval")
root.geometry("800x600")

w = 600
h = 400
x = w // 2
y = h // 2

my_canvas = Canvas(root, width=w, height=h, bg='black')
my_canvas.pack(pady=20)

my_circle = my_canvas.create_oval(x, y, x   20, y   20, fill='cyan')


def left(event):
    x1, y1, x2, y2 = get_canvas_position()
    if x1 > 0:
        x = -10
        y = 0
        my_canvas.move(my_circle, x, y)


def right(event):
    x1, y1, x2, y2 = get_canvas_position()
    if x2 < w:
        x = 10
        y = 0
        my_canvas.move(my_circle, x, y)


def up(event):
    x1, y1, x2, y2 = get_canvas_position()
    if y1 > 0:
        x = 0
        y = -10
        my_canvas.move(my_circle, x, y)


def down(event):
    x1, y1, x2, y2 = get_canvas_position()
    if y2 < h:
        x = 0
        y = 10
        my_canvas.move(my_circle, x, y)


def get_canvas_position():
    return my_canvas.coords(my_circle)


root.bind('<Left>', left)
root.bind('<Right>', right)
root.bind('<Up>', up)
root.bind('<Down>', down)

root.mainloop()

CodePudding user response:

The canvas object is stored via 2 sets of coordinates [x1, y1, x2, y2]. You should check against the objects current location by using the .coords() method. The dimensions of the canvas object will affect the coordinates.

def left(event):
    x = -10
    y = 0
    if my_canvas.coords(my_circle)[0] > 0:  # index 0 is X coord left side object.
        my_canvas.move(my_circle, x, y)

def right(event):
    x = 10
    y = 0
    # The border collision now happens at 600 as per var "w" as previously defined above.
    if my_canvas.coords(my_circle)[2] < w:  # index 2 is X coord right side object.
        my_canvas.move(my_circle, x, y)

Now repeat a similar process for up and down.

  • Related