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.
Related
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()
I found the following piece of code here.
from tkinter import *
canvas_width = 500
canvas_height = 150
def paint( event ):
python_green = "#476042"
x1, y1 = ( event.x - 1 ), ( event.y - 1 )
x2, y2 = ( event.x + 1 ), ( event.y + 1 )
w.create_oval( x1, y1, x2, y2, fill = python_green )
master = Tk()
master.title( "Painting using Ovals" )
w = Canvas(master,
width=canvas_width,
height=canvas_height)
w.pack(expand = YES, fill = BOTH)
w.bind( "<B1-Motion>", paint )
message = Label( master, text = "Press and Drag the mouse to draw" )
message.pack( side = BOTTOM )
master.mainloop()
It lets you draw on a Tkinter canvas by dragging your mouse around. It works just fine when I move my mouse very very slowly but the moment I move it a bit faster, the lines end up broken. Here's what I mean:
Screenshot of the Tkinter window
The line on the top was drawn slowly.
The one on the bottom, rather quickly.
As you can see, the bottom one is missing points in many places. How do I fix this?
If you want to draw a line, you need to register the coordinates of where the mouse moves and create line based on that using create_line method because it connects those points. So append positions of mouse to a list and draw a line and use the coordinates from that list. When you start drawing (click mouse), append the starting coordinates. Then on movement append the coordinates, delete the previous line (basically updating) and draw a new one. When mouse button is released clear the list of points and set the current line id to None to indicate that currently no line is drawn.
import tkinter as tk
line_id = None
line_points = []
line_options = {}
def draw_line(event):
global line_id
line_points.extend((event.x, event.y))
if line_id is not None:
canvas.delete(line_id)
line_id = canvas.create_line(line_points, **line_options)
def set_start(event):
line_points.extend((event.x, event.y))
def end_line(event=None):
global line_id
line_points.clear()
line_id = None
root = tk.Tk()
canvas = tk.Canvas()
canvas.pack()
canvas.bind('<Button-1>', set_start)
canvas.bind('<B1-Motion>', draw_line)
canvas.bind('<ButtonRelease-1>', end_line)
root.mainloop()
Also:
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
After I run the code it makes my window unmovable, and I was wondering how would i make it interact with
MOUSE1
EDIT1: So this is what i came up with, but it doesnt work like it should, it just "teleports" the window around.
from tkinter import*
root = Tk()
root.overrideredirect(True)
#takes x, y coordinates of your mouse when u realese MOUSE1
def move_window(event):
global root
x_coord = event.x
y_coord = event.y
y_coord = str(event.y)
x_coord = str(event.x)
root.geometry('+'+x_coord+'+'+y_coord)
root.bind('<ButtonRelease-1>', move_window)
root.mainloop()
EDIT2: SOLVED! I realised the position of the mouse in the code above takes the position x,y INSIDE the tkinter window, not on the screen, I will use the module
pyautogui for that
I want to change the color of rectangle after a certain period of time.
I tried root.after() method but it is not working.
import time
from tkinter import *
def task():
canvas= Canvas()
canvas.create_rectangle(0,0,100,100,fill='red')
canvas.pack()
time.sleep(2)
canvas.create_rectangle(0,0,100,100,fill='blue')
canvas.pack()
time.sleep(2)
print("Testing...")
root = Tk()
canvas = Canvas(root)
while(1):
task()
root.mainloop()
Given code running continuously and root windows get hang for certain time. Rectangle color should change after 2 seconds of delay.
Using time.sleep() hangs the window as well as while loop. To use time.sleep
in tkinter we use after(ms) (ms-milliseconds) in the functions so the GUI won't hang.
While does the same, so we use after(ms, callback, args) function.
Here is an example of what you are trying to achieve. The rectangle will change his color every 1000ms (1 sec) from red to blue - blue to red so on. Also in your code you were creating a new canvas and rectangle every 4 secs. What I did is, I defined one canvas and one rectangle outside the task() function and gave the rectangle a tag (tag='rect') for the reference through which edit that one rectangle's color without creating unnecessary items. I hope this helped you.
Example:
from tkinter import *
root = Tk()
canvas = Canvas(root)
canvas.pack()
canvas.create_rectangle(0,0,100,100,fill='red', tag='rect')
def task():
l = root.after(1000, task)
if int(l.split('#')[1]) % 2 == 0:
canvas.itemconfig('rect', fill='blue')
else:
canvas.itemconfig('rect', fill='red')
task()
root.mainloop()
I have an implementation of k-NN algorithm in Python, that returns the class label of an input. What I need is to show an image assigned to the class label in one window while output is coming (by refreshing the window). Problem is, I am not very experienced in GUI programming, thus I need some resources and assistance to start with. What libraries, books and tutorials could you recommend? Pieces of code would be appreciated too.
There are many libraries allow you add images to your program such as Turtle, PIL.ImagTk and Canvas and you can even use Pygame to a best performance.
PIL.ImagTk and Canvas:
from Tkinter import *
from PIL import ImageTk
backgroundImage = PhotoImage("image path (gif/PPM)")
canvas = Canvas(width = 200, height = 200, bg = 'blue')
canvas.pack(expand = YES, fill = BOTH)
image = ImageTk.PhotoImage(file = "C:/Python27/programas/zimages/gato.png")
canvas.create_image(10, 10, image = image, anchor = NW)
mainloop()
Turtle:
import turtle
screen = turtle.Screen()
# click the image icon in the top right of the code window to see
# which images are available in this trinket
image = "rocketship.png"
# add the shape first then set the turtle shape
screen.addshape(image)
turtle.shape(image)
screen.bgcolor("lightblue")
move_speed = 10
turn_speed = 10
# these defs control the movement of our "turtle"
def forward():
turtle.forward(move_speed)
def backward():
turtle.backward(move_speed)
def left():
turtle.left(turn_speed)
def right():
turtle.right(turn_speed)
turtle.penup()
turtle.speed(0)
turtle.home()
# now associate the defs from above with certain keyboard events
screen.onkey(forward, "Up")
screen.onkey(backward, "Down")
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.listen()
Now let’s change the background
import turtle
screen = turtle.Screen()
# this assures that the size of the screen will always be 400x400 ...
screen.setup(400, 400)
# ... which is the same size as our image
# now set the background to our space image
screen.bgpic("space.jpg")
# Or, set the shape of a turtle
screen.addshape("rocketship.png")
turtle.shape("rocketship.png")
move_speed = 10
turn_speed = 10
# these defs control the movement of our "turtle"
def forward():
turtle.forward(move_speed)
def backward():
turtle.backward(move_speed)
def left():
turtle.left(turn_speed)
def right():
turtle.right(turn_speed)
turtle.penup()
turtle.speed(0)
turtle.home()
# now associate the defs from above with certain keyboard events
screen.onkey(forward, "Up")
screen.onkey(backward, "Down")
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.listen()
for Turtle:
http://blog.trinket.io/using-images-in-turtle-programs/