Can't move image with time delay - python

I'm trying to figure out how to make a scrolling image in python, but I got into some issues with delay. I need the image to move after the canvas has rendered, and I also need it to move with a time delay. Here is my current code:
from Tkinter import *
import ImageTk
import time
def scrollToTop(imaget):
for x in range(100, 20, -1):
canvas.move(imaget, 0, -1)
t = Tk()
canvas = Canvas(t,height=256,width=256)
canvas.pack()
arrows = [1]
arrows[0] = ImageTk.PhotoImage(file="arrow.bmp")
image = canvas.create_image(20,100,image=arrows[0],tags="token")
t.mainloop();
scrollToTop(image);
I tried playing around where the scrollToTop() function was, and I also tried time.delay(0.1), all to no avail. I could try something like an Update() function, that measures the time passed from a "game time" variable...
Thanks in advance!

First: main loop t.mainloop() run till you close program so every instruction after t.mainloop() will be run after you close program.
You can use timer to call scrollToTop (for example) every 1 second (1000 millisecond)
from Tkinter import *
import ImageTk
import time
def scrollToTop():
print "I'm in scrollToTop()"
canvas.move(image, 0, -1)
t.after(1000, scrollToTop)
t = Tk()
canvas = Canvas(t,height=256,width=256)
canvas.pack()
arrows = [1]
arrows[0] = ImageTk.PhotoImage(file="arrow.bmp")
image = canvas.create_image(20,100,image=arrows[0],tags="token")
scrollToTop()
t.mainloop();
EDIT:
t.after() require function name without () so if you need to run functiion with arguments use lambda function
from Tkinter import *
import ImageTk
import time
def scrollToTop(imaget):
print "I'm in scrollToTop()"
canvas.move(imaget, 0, -1)
t.after(1000, lambda:scrollToTop(imaget))
t = Tk()
canvas = Canvas(t,height=256,width=256)
canvas.pack()
arrows = [1]
arrows[0] = ImageTk.PhotoImage(file="arrow.bmp")
image = canvas.create_image(20,100,image=arrows[0],tags="token")
scrollToTop(image)
t.mainloop();

Related

How can you run two python tkinter files simultaneously when one has a loop in it?

I have made a tkinter country guessing game witch works fine however takes along time to run. So i made a loading screen for it with a looping animation on in a separate file. I cant find a way to run the loading screen first and then run the game whilst the animation on the loading screen is still running.
Loading screen code:
from tkinter import *
from time import *
import os
import random
run = 0
loads = True
dotnum = 0
def task():
sleep(2)
root.destroy()
root = Tk()
root.title("Loading...")
root.geometry("1280x720")
Background = PhotoImage(file = "Images\Loadscreen.png")
Loaders = PhotoImage(file = "Images\Loader.gif")
image = Label(root,width=1000,height=500,image=Background)
image.place(x=0, y=0, relwidth=1, relheight=1)
frameCnt = 16
frames = [PhotoImage(file='Images\Loader.gif',format = 'gif -index %i' %(i)) for i in range(frameCnt)]
def update(ind):
frame = frames[ind]
ind += 1
if ind == frameCnt:
ind = 0
loadanim.configure(image=frame)
root.after(100, update, ind)
loadanim = Label(root, bg = "black")
loadanim.place(x = 450, y = 450)
root.after(0, update, 0)
root.mainloop()
To run the loading screen first, you can call the loading screen code before calling the game code.
You can modify the code to pass a function as an argument to the loading screen, and then call this function after the loading screen is destroyed. This will allow you to run the game code after the loading screen is done.
For example:
def run_game():
# game code here
pass
def run_loading_screen(callback):
# loading screen code here
root.after(2000, callback)
root.mainloop()
run_loading_screen(run_game)
Here, run_game is the function containing the game code, and run_loading_screen is the function containing the loading screen code. The run_loading_screen function takes a callback argument, which is the function to be called after the loading screen is destroyed. In the loading screen code, the root.after method is used to call the callback function after 2000 milliseconds (2 seconds).

How to rotate a image in Python tkinter Window

I am working on a python messaging application using tkinter and i need a loading screen animation but none of them where fitting with my purpose so i Tried to rotate a image in python continusly which will look like a animation.
This is the image i want to ratate for some time in tkinter
The application code
i only need a simple tkinter window with the rotating screen
I tried google and i got this code to rote a image
from PIL import Image # Import Image class from the library.
image = Image.open("file.jpg") # Load the image.
rotated_image = image.rotate(180) # Rotate the image by 180 degrees.
rotated_image.save("file_rotated.jpg")
So i tried using this code like this:-
from tkinter import *
from PIL import ImageTk, Image
import os
root = Tk()
c = Canvas(root, width=700, height=700)
c.pack()
while True:
img = ImageTk.PhotoImage(Image.open(r"Loading_Icon.png"))
c.create_image(100, 100, image=img, anchor=NW)
image = Image.open(Loading_Icon.png") # Load the image.
rotated_image = image.rotate(30)
os.remove("Loading_Icon.png")
rotated_image.save("Loding_Icon.png")
root.mainloop()
c.delete("all")
Look at this:
from PIL import Image, ImageTk
import tkinter as tk
# Load the original image
pil_img = Image.open("pawn.black.png")
def loading_loop(i=0):
global tk_img
print(f"Loop {i}")
# If the prgram has loaded, stop the loop
if i == 13: # You can replace this with your loading condition
return
# Rotate the original image
rotated_pil_img = pil_img.rotate(30*i)
tk_img = ImageTk.PhotoImage(rotated_pil_img)
# put the rotated image inside the canvas
canvas.delete("all")
canvas.create_image(0, 0, image=tk_img, anchor="nw")
# Call `loading_loop(i+1)` after 200 milliseconds
root.after(200, loading_loop, i+1)
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack()
# start the tkinter loop
loading_loop()
root.mainloop()
It loads the original image then it start a tkinter loop which runs loading_loop every 200 milliseconds. Inside loading_loop, I rotate the image 30*i degrees, where i is the iteration number. Then I put the image inside the canvas.
Notice how I only call .mainloop() once and there is no while True loop. Those are best practises for when using tkinter.
It's best to create only 1 image inside the canvas and just reconfigure it but that will make the code longer.

Python tkinter time delay before placing/ removing images

I have created a python tkinter program, where I want to display a series of images on a window, where the image changes every 6 seconds. When I use the code below, the whole program freezes for the entire 6 seconds.
loopey = "Fal"
while loopey == "Fal":
time.sleep(6)
menupic.place_forget()
menupic2.place(x=602,y=180)
home.update()
time.sleep(6)
menupic2.place_forget()
menupic.place(x=602,y=180)
home.update()
I also tried to use the after() function, but had the same issue.
def deletion(thing):
thing.place_forget()
while True:
home.after(6000, deletion(menupic))
menupic2.place(x=602,y=180)
home.update()
home.after(6000, deletion(menupic2))
menupic.place(x=602,y=180)
home.update()
I would do it like this:
from tkinter import *
from PIL import Image, ImageTk
from random import randint
import numpy as np
def place_image():
npimg = np.zeros([100,100,3],dtype=np.uint8)
npimg.fill(randint(0, 255))
pilimg = Image.fromarray(npimg)
tkimg = ImageTk.PhotoImage(pilimg)
label.img = tkimg
label.configure(image=tkimg)
home.after(6000, place_image)
home = Tk()
label = Label(home, text="test")
label.place(x=0, y=0)
home.after(6000, place_image)
home.mainloop()
If you use after() also in the function you can still interact with the window.
It wil still loop trought every 6 seconds.

Slide show program, event processing

I need the images to change if the cursor is inside the window without moving, but I managed to make the image changes only if the cursor is moving inside the window, how can I change the code?
from itertools import cycle
import tkinter as tk
from PIL import ImageTk, Image
import glob
image_files = glob.glob("*.jpg")
root = tk.Toplevel()
root.geometry("1600x900")
pictures = cycle((ImageTk.PhotoImage(file=image), image) for image in image_files)
picture_display = tk.Label(root)
picture_display.pack()
def show_slides(event):
img_object, img_name = next(pictures)
root.after(500, picture_display.config(image=img_object))
root.bind("<Motion>", show_slides)
root.mainloop()
You could bind the <Enter> and <Leave> events and use a flag to control the call, followed by using the after method to loop the function.
def show_slides(event=None):
global change_slide
img_object, img_name = next(pictures)
picture_display.config(image=img_object)
change_slide=root.after(500,show_slides)
def stop_slides(event):
root.after_cancel(change_slide)
root.bind("<Enter>", show_slides)
root.bind("<Leave>", stop_slides)
UPDATE
Using a flag might cause multiple calls being scheduled it the events happen during the 500ms delay, you can use after_cancel to terminate it.
You can calculate cursor position in loop and show image if it's located within tkinter window:
import glob
import tkinter as tk
from PIL import ImageTk
from itertools import cycle
class App(object):
def __init__(self):
self.root = tk.Tk()
self.root.geometry('900x600')
self.lbl = tk.Label(self.root)
self.lbl.pack()
files = glob.glob('*.jpg')
self.images = cycle((ImageTk.PhotoImage(file=f), f) for f in files)
self.show()
self.root.mainloop()
def show(self):
abs_coord_x = self.root.winfo_pointerx() - self.root.winfo_rootx()
abs_coord_y = self.root.winfo_pointery() - self.root.winfo_rooty()
if 0 <= abs_coord_x <= self.root.winfo_width() and 0 <= abs_coord_y <= self.root.winfo_height():
img_object, img_name = next(self.images)
self.lbl.config(image=img_object)
self.root.after(1000, self.show)
App()

Python/Tkinter background not changing colours when configured to

I am trying to create a harmless prank joke on my friends, and I want the background of a python tkinter window(not canvas) to change to a random colour every second, then, after ten rounds, it will destroy itself. The problem is that when root.config(background=random_colour)is called, it will not change it's background colour. The entire code is below:
from tkinter import *
import pyglet
import time
import random
root = Tk()
text = Label( padx = 1000, pady = 999, text = 'VIRUS!' )
text.pack()
text.config(font=('Courier', 44))
root.attributes("-fullscreen", True)
root.update()
I'm cutting this bit out because it's just a list of all the named colours in python(It's called COLOURS).
for x in range(0, 9):
colours_length = len(COLOURS)
number = random.randint(0, colours_length)
random_colour = COLOURS[number]
root.config(background=random_colour)
time.sleep(1)
root.update()
root.destroy()
I've took acw1668's advice from the comments section, and it works now. Turns out that the label was covering the entire root window, and that was why it wasn't working.

Categories

Resources