theerrormagnet
theerrormagnet

Reputation: 314

Python Tkinter - How to return a Widget

My goal is to write a program, that inserts an object (for example a rectangle)
that can be moved after insertion by using the arrow keys.
I am able to place a rectangle on a canvas, but I can't interact with the
rectangle, because I cannot return a Widget from an event function.

So in this program I can move the rectangle that is already on the canvas,
but when I insert another rectangle I am still moving the first rectangle.

from tkinter import *

root = Tk()

my_canvas = Canvas(root, width = 500, height = 500, bg = "white")
my_canvas.grid(row = 0, column = 0)

my_object = my_canvas.create_rectangle(50, 150, 250, 50, fill = "red")


def left(event):
  my_canvas.move(my_object, -10, 0)
  
def right(event):
  my_canvas.move(my_object, 10, 0)
  
def up(event):
  my_canvas.move(my_object, 0, -10)
  
def down(event):
  my_canvas.move(my_object, 0, 10)
  
def opamp(event):
  #the following code does not overwrite my_object...
  my_object = my_canvas.create_rectangle(100, 200, 250, 50, fill = "black")
  my_label = Label(root, text = "your mouse is at " + str(event.x) + " " + str(event.y))
  my_label.grid(row = 1, column = 1)
  #returning my_object does not work either

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


root.mainloop()

Upvotes: 0

Views: 249

Answers (1)

acw1668
acw1668

Reputation: 47193

You can use tag instead of item ID returned by .create_rectangle() in the movement functions:

from tkinter import *

ACTIVE = "active"  # tag name for the *active* item

root = Tk()

my_canvas = Canvas(root, width=500, height=500, bg="white")
my_canvas.grid(row=0, column=0)

my_canvas.create_rectangle(50, 150, 250, 50, fill="red", tag=ACTIVE) # make it *active*

def left(event):
  my_canvas.move(ACTIVE, -10, 0)
  
def right(event):
  my_canvas.move(ACTIVE, 10, 0)
  
def up(event):
  my_canvas.move(ACTIVE, 0, -10)
  
def down(event):
  my_canvas.move(ACTIVE, 0, 10)
  
def opamp(event):
  my_canvas.dtag(ACTIVE, ACTIVE) # clear current active tag
  my_canvas.create_rectangle(100, 200, 250, 50, fill="black", tag=ACTIVE) # make it *active*
  #my_label = Label(root, text=f"your mouse is at {event.x} {event.y}")
  #my_label.grid(row=1, column=0)

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

root.mainloop()

Upvotes: 1

Related Questions