about Python canvas moving object - python-3.x

I want to move a rectangle from left to right with a step of 50,but the canvas doesn't draw the rectangle until it arrive right side.
import tkinter as tk
import time
root=tk.Tk()
c_width,c_height=500,250
cv = tk.Canvas(root,bg = 'white',width=c_width,height=c_height)
l_x=0
l_y=0
r_x=50
r_y=50
step=50
r1=cv.create_rectangle(l_x,l_y,r_x,r_y,fill='red')
while l_x<c_width-50:
cv.delete(r1)
l_x=l_x+step
r_x=r_x+step
r1=cv.create_rectangle(l_x,l_y,r_x,r_y,fill='red')
print(c_width,l_x)
time.sleep(1)
cv.pack()
root.mainloop()

It is not recommended to use while/for loop in tkinter application because it will block the tkinter mainloop() from handling pending events and updates. Use .after() instead.
Also you don't need to delete and recreate the rectangle item, just move the rectangle item using cv.move().
Below is the update code:
import tkinter as tk
root = tk.Tk()
c_width, c_height = 500, 250
cv = tk.Canvas(root, bg='white', width=c_width, height=c_height)
cv.pack()
l_x = 0
l_y = 0
r_x = 50
r_y = 50
step = 50
r1 = cv.create_rectangle(l_x, l_y, r_x, r_y, fill='red')
def move_rect(x):
# move the rectangle by "step" pixels horizontally
cv.move(r1, step, 0)
x += step
if x < c_width:
cv.after(1000, move_rect, x)
cv.after(1000, move_rect, r_x)
root.mainloop()

Related

How to change the button position when pressed in tkinter python

please tell me how to change the position of the button in tkinter. I predicted that it could be done by button['padx' = 4], but it doesn't work. Do you know how to do it?
from tkinter import ttk
import random
window = tk.Tk()
window.geometry('512x512')
def click():
pass
button = ttk.Button(
text="No",
command=click
).pack(padx=5, pady=15)
window.mainloop()
I instead assigned 2 variables to random integers, and then updated the position of the button with those variables. If you want the random position to be a wider area increase the number "100" in "random_int".
from tkinter import *
import random
window = Tk()
window.geometry('512x512')
x = 5
y = 15
def click():
random_int = random.randint(0, 100)
x = (random_int)
random_int = random.randint(0, 100)
y = (random_int)
button.place(x=x, y=y)
button = Button(text="No", command=click)
button.pack(padx=5, pady=15)
window.mainloop()

I want to display images that are send to a specific folder in a sort of slideshow

I have a piece of code right now that when i start it up it creates a black canvas and displays a image on it (With Tkinter) that i randomly grab from a folder i have selected with photos in it.
But right now i have to press esc to go to the next image. I would like it to be on a timer.
It also won't go to the next image. It says pyimage2 does not exist.
It would be great if someone can help me. I am incredibly new to python and don't know that much.
from PIL import Image
import os, random
import time
import sys
if sys.version_info[0] == 2:
import Tkinter
tkinter = Tkinter
else:
import tkinter
from PIL import Image, ImageTk
i = True
def showPIL(pilImage):
root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
canvas = tkinter.Canvas(root,width=w,height=h)
canvas.pack()
canvas.configure(background='black')
imgWidth, imgHeight = pilImage.size
if imgWidth > w or imgHeight > h:
ratio = min(w/imgWidth, h/imgHeight)
imgWidth = int(imgWidth*ratio)
imgHeight = int(imgHeight*ratio)
pilImage = pilImage.resize((imgWidth,imgHeight), Image.ANTIALIAS)
image = ImageTk.PhotoImage(pilImage)
imagesprite = canvas.create_image(w/2,h/2,image=image)
root.mainloop()
while i == True:
timer = 0
while timer < 5:
path = "C:/Users/thymen.hummel/PycharmProjects/HelloWorld/Images"
random_filename = random.choice([x
for x in os.listdir(path)
if os.path.isfile(os.path.join(path, x))
])
pilImage = Image.open(f'C:/Users/thymen.hummel/PycharmProjects/HelloWorld/Images/{random_filename}')
showPIL(pilImage)
print(random_filename)
timer += 1
time.sleep(5)
check https://www.geeksforgeeks.org/python-convert-speech-to-text-and-text-to-speech/. Instead of typing, you can name the name of the image and the program will open it.
To do it by timer, you can do it using pygame.time.wait(). It takes input in milliseconds. see https://www.pygame.org/docs/ref/time.html for more information.

Is there any command in turtle which stops turtle from further drawing?

I am creating a tkinter based program which used turtle graphics to draw graphs. I have a button which draws a square in the screen. But when I press that button while turtle is drawing something else, the turtle start to draw square and after finishing it again continue its previous task. I don't want it to continue it previous function. I want to directly stop it wherever it is and just do its new job.
This is the sample code but this is not actually what I need it for. I have tried to simplify the problem.
import tkinter as tk
from turtle import RawTurtle
def square():
t.up()
t.home()
t.down()
for i in range(4):
t.fd(100)
t.rt(90)
def drawseries():
l = 2
for i in range(100):
t.fd(l)
t.lt(90)
l += 2
root = tk.Tk()
button = tk.Button(root,command = square, text = 'Draw Square')
button.pack()
canvas = tk.Canvas(root, width = 500, height = 500)
canvas.pack()
t = RawTurtle(canvas)
drawseries()
You are always calling the drawseries() command at the end of the file. When the for loop is done, it calls drawseries() again.

Trouble filling a Python tkinter/turtle window with squares

I'm having trouble with getting the turtle.begin_fill() / turtle.end_fill() commands to work in a tkinter window. I want to have the program draw a bunch of coloured cells onto the screen in a 64x32 grid. This the whole code to set up the window and draw however it simply doesn't do anything after setting up a window:
import turtle as tu
import tkinter as tk
axis = []
num = -512
for i in range(0,64):
axis.append(num)
num = num + 16
def drawworld(*args):
for i in range(0,64):
for j in range(0,32):
tu.goto(axis[i],axis[j]+256)
tu.pd()
tu.color=("#ffff00")
tu.begin_fill()
for k in range(0,4):
tu.fd(16)
tu.lt(90)
tu.end_fill()
tu.pu()
root = tk.Tk()
root.title("game")
root.resizable(False, False)
canvas = tk.Canvas(master = root, width = 1024, height = 512)
canvas.grid(row=0, column=0, columnspan=10)
tu = tu.RawTurtle(canvas)
tu.speed(50)
tu.pu()
tu.ht()
drawworld()
root.mainloop()
however, if I were to comment out the fill lines, the code works perfectly (without colouring the boxes) which means there must be something wrong with:
tu.color=("#ffff00")
tu.begin_fill()
for k in range(0,4):
tu.fd(16)
tu.lt(90)
tu.end_fill()
tu.pu()
I've looked up the documentation and this should be perfect syntax. What am I doing wrong?
I believe your problem is this line:
tu.color=("#ffff00")
which probably should be:
tu.color("#ffff00")
to set the color, you don't assign to the turtle's color property but rather invoke the turtle's .color() method. Your code with this change and some other cleanup:
import tkinter as tk
from turtle import RawTurtle
axis = []
num = -512
for _ in range(64):
axis.append(num)
num += 16
def drawworld():
for i in range(64):
for j in range(32):
tu.goto(axis[i], axis[j] + 256)
tu.pendown()
tu.color("#ffff00")
tu.begin_fill()
for _ in range(4):
tu.forward(16)
tu.left(90)
tu.end_fill()
tu.penup()
root = tk.Tk()
root.title("game")
root.resizable(False, False)
canvas = tk.Canvas(master=root, width=1024, height=512)
canvas.grid(row=0, column=0, columnspan=10)
tu = RawTurtle(canvas)
tu.speed('fastest')
tu.hideturtle()
tu.penup()
drawworld()
root.mainloop()
However, this is a painfully slow way to go about this. There are faster ways, here's one that uses stamping to speed up the process:
import tkinter as tk
from turtle import RawTurtle
from random import random
CUBE_SIZE = 16
CURSOR_SIZE = 20
WIDTH, HEIGHT = 1024, 512
axis = []
num = -HEIGHT
for _ in range(WIDTH // CUBE_SIZE):
axis.append(num)
num += CUBE_SIZE
def drawworld():
for i in range(WIDTH // CUBE_SIZE):
tu.goto(axis[i] + CUBE_SIZE // 2, axis[0] + HEIGHT // 2 + CUBE_SIZE // 2)
for j in range(HEIGHT // CUBE_SIZE):
tu.color(random(), random(), random())
tu.stamp()
tu.forward(CUBE_SIZE)
root = tk.Tk()
root.title("game")
root.resizable(False, False)
canvas = tk.Canvas(master=root, width=WIDTH, height=HEIGHT)
canvas.grid(row=0, column=0, columnspan=10)
tu = RawTurtle(canvas)
tu.shape('square')
tu.shapesize(CUBE_SIZE / CURSOR_SIZE)
tu.speed('fastest')
tu.hideturtle()
tu.setheading(90)
tu.penup()
drawworld()
root.mainloop()

Generate 10 balls in tkinter canvas

Ok guys.
I am trying to generate 10 balls of random color in Tkinter canvas when I click the generate button.
Program works, and random color choice works for the ball, but I only get one ball generated at a time.
Every time I click the button it randomly moves the ball around, but all I want is 10 balls in 10 random positions at a time. I am using Python 3.4 on a Linux box.
This is a code I've got:
from tkinter import *
import random # to generate random balls
colors = ["red", "blue", "purple", "green", "violet", "black"]
class RandomBalls:
"""
Boilerplate code for window in Tkinter
window = Tk()
window.title("Random title")
window.mainloop()
"""
def __init__(self):
"""
Initialize the window and add two frames, one with button, and another one with
canvas
:return:
"""
window = Tk()
window.title("Random balls")
# A canvas frame
frame1 = Frame(window)
frame1.pack()
self.canvas = Canvas(frame1, width = 200, height = 300, bg = "white")
self.canvas.pack()
# A button frame
frame2 = Frame(window)
frame2.pack()
displayBtn = Button(frame2, text = "Display", command = self.display)
displayBtn.pack()
window.mainloop()
def display(self):
for i in range(0, 10):
self.canvas.delete("circle") # delete references to the old circle
self.x1 = random.randrange(150)
self.y1 = random.randrange(200)
self.x2 = self.x1 + 5
self.y2 = self.y1 + 5
self.coords = self.x1, self.y1, self.x2, self.y2
self.canvas.create_oval(self.coords, fill = random.choice(colors), tags = "circle")
self.canvas.update()
RandomBalls()
Every time through your loop you are deleting everything you created before, including what you created the previous iteration. Move the delete statement outside of the loop:
def display(self):
self.canvas.delete("circle")
for i in range(0, 10):
...

Resources