How to move a Canvas image using Tkinter? - python

Guys I am working on a code which needs to move an image in python using Tkinter(canvas)
This is creating problems for me. The image is being displayed but it is not moving.
from Tkinter import *
root = Tk()
root.title("Click me!")
def next_image(event):
global toggle_flag
global x, y, photo1
# display photo2, move to right, y stays same
canvas1.create_image(x+10, y, image=photo1)
canvas1.create_image(x+20, y, image=photo1)
canvas1.create_image(x+30, y, image=photo1)
canvas1.create_image(x+40, y, image=photo1)
canvas1.create_image(x+50, y, image=photo1)
canvas1.create_image(x+60, y, image=photo1)
canvas1.create_image(x+70, y, image=photo1)
canvas1.create_image(x+100, y, image=photo1)
image1 = "C:\Python26\Lib\site-packages\pygame\examples\data\ADN_animation.gif" #use some random gif
photo1 = PhotoImage(file=image1)
# make canvas the size of image1/photo1
width1 = photo1.width()
height1 = photo1.height()
canvas1 = Canvas(width=width1, height=height1)
canvas1.pack()
# display photo1, x, y is center (anchor=CENTER is default)
x = (width1)/2.0
y = (height1)/2.0
canvas1.create_image(x, y, image=photo1)
canvas1.bind('<Button-1>', next_image) # bind left mouse click
root.mainloop()

Canvas provides move method. Arguments are item you want to move, relative x offset from the previous position, y offset.
You need to save the return value of the create_image to pass it to the move method.
Also make sure the canvas is expandable (pack(expand=1, fill=BOTH) in the following code)
from Tkinter import *
root = Tk()
def next_image(event):
canvas1.move(item, 10, 0) # <--- Use Canvas.move method.
image1 = r"C:\Python26\Lib\site-packages\pygame\examples\data\ADN_animation.gif"
photo1 = PhotoImage(file=image1)
width1 = photo1.width()
height1 = photo1.height()
canvas1 = Canvas(width=width1, height=height1)
canvas1.pack(expand=1, fill=BOTH) # <--- Make your canvas expandable.
x = (width1)/2.0
y = (height1)/2.0
item = canvas1.create_image(x, y, image=photo1) # <--- Save the return value of the create_* method.
canvas1.bind('<Button-1>', next_image)
root.mainloop()
UPDATE according to the comment
Using after, you can schedule the function to be called after given time.
def next_image(event=None):
canvas1.move(item, 10, 0)
canvas1.after(100, next_image) # Call this function after 100 ms.

Related

Tkinter smooth transition between frames

# Import the required libraries
from tkinter import *
from PIL import Image, ImageTk
# Create an instance of tkinter frame
win = Tk()
# Set the size of the tkinter window
win.geometry("700x350")
# Define a Canvas widget
canvas = Canvas(win, width=600, height=400, bg="white")
canvas.pack(pady=20)
# Add Images to Canvas widget
x = 250
y = 120
image = ImageTk.PhotoImage(Image.open('map.png'))
img = canvas.create_image(x, y, anchor=NW, image=image)
def left(e):
global x, y
x -= 0.9
canvas.coords(img, x, y)
def right(e):
global x, y
x += 0.9
canvas.coords(img, x, y)
def up(e):
global x, y
y -= 0.9
canvas.coords(img, x, y)
def down(e):
global x, y
y += 0.9
canvas.coords(img, x, y)
# Bind the move function
win.bind("<Left>", left)
win.bind("<Right>", right)
win.bind("<Up>", up)
win.bind("<Down>", down)
win.mainloop()
map.png is https://www.dropbox.com/s/wfq4skai66nexxr/map.png?dl=0. If you press left or right arrow keys, you will see the black words look slightly lagging. Is there a way to fix that without changing the 0.9?

Why doesn't this image move when the key is pressed?

Python and Tkinter nebwie. I tried making an image in tkinter and have it move using the arrows. The image shows just it should, but when I try to move it using the arrows, it doesn't work at all. Any idea why? I use python 2.7.18 and I'm on the latest version of Ubuntu
from Tkinter import *
############
#things
w = 500
h = 500
width=w
height=h
#############
######################################################################
#window
window = Tk()
window.title("Moving image")
canvas = Canvas(window, width = 500, height = 500)
canvas.pack()
my_image = PhotoImage(file="/home/user/Documents/ddd.png")
canvas.create_image(260, 125, anchor = NW, image=my_image)
#######################################################################
################################
#var
def up(event):
x = 0
y = -10
canvas.move(my_image, x, y)
def down(event):
x = 0
y = 10
canvas.move(my_image, x, y)
def left(event):
x = -10
y = 0
canvas.move(my_image, x, y)
def right(event):
x = 10
y = 0
canvas.move(my_image, x, y)
###############################
###############################
#binds
window.bind("<Up>", up)
window.bind("<Down>", down)
window.bind("<Left>", left)
window.bind("<Right>", right)
window.mainloop()
##############################
You are trying to move the wrong object. Use the object, which is returned by canvas.create_image:
image_id = canvas.create_image(260, 125, anchor = NW, image=my_image)
...
canvas.move(image_id, x, y)
Alternatively, you can attach a tag to the image:
canvas.create_image(260, 125, anchor=NW, image=my_image, tag="move")
...
canvas.move("move", x, y)
This will move all objects, which have this specific tag attached.

Python tkinter get color from canvas

I have created a simple Tkinter application with a canvas widget like this:
from tkinter import *
root = Tk()
root.geometry("500x500-500+500")
canvas = Canvas(root, width = 400, height = 400, bg = "white")
canvas.pack()
canvas.create_line(0, 0, 200, 100, width = 20, fill = "black")
root.mainloop()
My question is, how can I get the color of the canvas in a specific position? Say for instance I clicked somewhere on the line, how can I get back the color "black" from that?
In other words, if I wanted a function like this,
def getColor(cnvs, event = None):
x = event.x
y = event.y
# somehow gets the color of cnvs at position (x, y) and stores it as color
return color
how would I go about doing that?
You can take a screen shot of the canvas using Pillow.ImageGrab module and get the required pixel color from the snapshot image:
from PIL import ImageGrab
def get_color(cnvs, event):
x, y = cnvs.winfo_rootx()+event.x, cnvs.winfo_rooty()+event.y
# x, y = cnvs.winfo_pointerx(), cnvs.winfo_pointery()
image = ImageGrab.grab((x, y, x+1, y+1)) # 1 pixel image
return image.getpixel((0, 0))
Note that the color returned is in (R, G, B) format.

How to change window geometry in tkinter using after?

What I want to achieve is displaying an image on another application window with regard to its coordinates. For example, it should appear 100 pixels down and 100 pixels left to the left upper corner. I am using transparent window for the image, and it displays an image properly but it doesn't update its coordinates.
Here is my code:
import tkinter as tk # Python 3
from functions import window_coordinates # it takes x, y, width, heigth of the window
x, y, w, h = window_coordinates("window_name")
def update_coordinates():
global x, y, w, h
x, y, w, h = window_coordinates("window_name")
root.geometry("+{}+{}".format(x + 100, y + 100))
print("update_coordinates function")
root = tk.Tk()
# The image must be stored to Tk or it will be garbage collected.
root.image = tk.PhotoImage(file='path/to/image.png')
label = tk.Label(root, image=root.image, bg='white')
root.overrideredirect(True)
root.geometry("+{}+{}".format(x+100, y+100))
root.lift()
root.wm_attributes("-topmost", True)
root.wm_attributes("-disabled", True)
root.wm_attributes("-transparentcolor", "white")
label.pack()
label.after(100, update_coordinates)
label.mainloop()
Thanks for help.
EDIT1: I put root.geometry("+{}+{}".format(x + 100, y + 100)) inside the function but it didn't help. Also I added print statement to see how this function works and it's called only once at the beginning.
OK, I found the answer. There was a mistake in the function. Callback didn't work. Right code:
import tkinter as tk # Python 3
from functions import window_coordinates
x, y, w, h = window_coordinates("3949206036")
def update_coordinates():
global x, y, w, h
x, y, w, h = window_coordinates("3949206036")
root.geometry("+{}+{}".format(x + 100, y + 100))
label.after(1, update_coordinates) # This addition was needed
root = tk.Tk()
# The image must be stored to Tk or it will be garbage collected.
root.image = tk.PhotoImage(file='d:/Python/Projects/Data-mining/samples/avatar.png')
label = tk.Label(root, image=root.image, bg='white')
root.overrideredirect(True)
root.geometry("+{}+{}".format(x+100, y+100))
root.lift()
root.wm_attributes("-topmost", True)
root.wm_attributes("-disabled", True)
root.wm_attributes("-transparentcolor", "white")
label.pack()
label.after(1, update_coordinates)
label.mainloop()

Move the mouse in a Canvas and display a point moving in the same way BUT in another canvas

I'm creating an interface with Tkinter (Python3) having two canvas. I want to moove the mouse over one canvas and to display a dot moving in the same way (as the mouse) but in the other canva.
I have tried this :
def motion(self,event):
x, y = event.x, event.y
self.dot=self.canvas.create_oval((x,y), (x,y), width=2, outline='red', fill='red')
The problem is that I can display the point but this one will remain. I have also tried to delete the dot after creating it, but this way it will not apprear :
def motion(self,event):
x, y = event.x, event.y
self.dot=self.canvas.create_oval((x,y), (x,y), width=2, outline='red', fill='red')
self.canvas.delete(self.dot)
Can someone help me ?
Thanks a lot
You don't have to create a new dot each time the mouse moves. Create the dot once and move it around with the canvas method coords(<item>, *new_coords). <item> is the canvas item id returned by create_oval (an int).
Here is an example:
import tkinter as tk
def on_move(event):
x, y = event.x, event.y
canvas2.coords(dot, x - 5, y - 5, x + 5, y + 5)
root = tk.Tk()
canvas1 = tk.Canvas(root)
canvas2 = tk.Canvas(root, bg='white')
canvas1.pack(side='left')
canvas2.pack(side='right')
dot = canvas2.create_oval(-10, -10, 0, 0, fill='black')
canvas1.bind('<Motion>', on_move)
root.mainloop()

Categories

Resources