Python Returns An Error When I Try To Quit The Application Window
Solution 1:
It looks like turtle uses tkinter. In Tk there's a method named protocol which you can use to control what happens when certain events happen, one of those being hitting the red 'X'.
In order to invoke that we need to get the root level window.
Placing
canvas = wn.getcanvas()
root = canvas.winfo_toplevel()
will set root as your root window.
From here you can use root.protocol("WM_DELETE_WINDOW", on_close)
to invoke a function named on_close
or whatever you want to name it.
Your function will probably look something like this.
def on_close():
globalrunningrunning=False
This will break you out of your loop and close your program.
Full Code.
import turtle
wn = turtle.Screen()
canvas = wn.getcanvas()
root = canvas.winfo_toplevel()
wn.title("Pong")
wn.bgcolor('black')
wn.setup(width=800, height=600)
wn.tracer(0)
#Score
score_a = 0
score_b = 0#paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5, stretch_len = 1)
paddle_a.penup()
paddle_a.goto(-350,0)
#paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid=5, stretch_len = 1)
paddle_b.penup()
paddle_b.goto(350,0)
#Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("circle")
ball.color("white")
ball.penup()
ball.goto(0,0)
ball.dx = 0.5
ball.dy = 0.5#pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,260)
pen.write("Player A: 0 Player B: 0", align="center", font=('Courier', 24, "normal"))
#Functiondef paddle_a_up():
y = paddle_a.ycor()
y+=20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y-=20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y+=20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y-=20
paddle_b.sety(y)
#Keyboard binding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
def on_close():
global running
running = False
root.protocol("WM_DELETE_WINDOW", on_close)
running = True
#main game loopwhile running:
wn.update()
#move the ball
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)
#borderif ball.ycor() > 280:
ball.sety(280)
ball.dy*=-1if ball.ycor() < -280:
ball.sety(-280)
ball.dy*=-1if ball.xcor() > 380:
ball.goto(0,0)
ball.dx*=-1
score_a+=1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
if ball.xcor() < -380:
ball.goto(0,0)
ball.dx*=-1
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align="center", font=('Courier', 24, "normal"))
#colliosionif (ball.xcor() > 330and ball.xcor() < 340) and (ball.ycor() < paddle_b.ycor() + 50and ball.ycor() > paddle_b.ycor() -50):
ball.setx(330)
ball.dx*=-1if (ball.xcor() < -330and ball.xcor() > -340) and (ball.ycor() < paddle_a.ycor() + 50and ball.ycor() > paddle_a.ycor() -50):
ball.setx(-330)
ball.dx*=-1
Solution 2:
We can solve this problem from within turtle, no need to drop down to tkinter underpinnings. Generally, you need to play by the rules. Specifically, no while running:
aka while True:
. Turtle is an event-based environment and you're not letting events get handled properly and thus the error messages.
Instead of the while
loop, we need an ontimer()
event:
from turtle import Screen, Turtle
FONT = ('Courier', 24, 'normal')
# Score
score_a = 0
score_b = 0# Functiondefpaddle_a_up():
paddle_a.sety(paddle_a.ycor() + 20)
defpaddle_a_down():
paddle_a.sety(paddle_a.ycor() - 20)
defpaddle_b_up():
paddle_b.sety(paddle_b.ycor() + 20)
defpaddle_b_down():
paddle_b.sety(paddle_b.ycor() - 20)
defsingle_step():
global score_a, score_b
# move the ball
ball.setposition(ball.xcor() + ball.dx, ball.ycor() + ball.dy)
# borderif ball.ycor() > 280:
ball.sety(280)
ball.dy *= -1elif ball.ycor() < -280:
ball.sety(-280)
ball.dy *= -1if ball.xcor() > 380:
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align='center', font=FONT)
if ball.xcor() < -380:
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write(f"Player A: {score_a} Player B: {score_b}", align='center', font=FONT)
# collisionif330 < ball.xcor() < 340and paddle_b.ycor() - 50 < ball.ycor() < paddle_b.ycor() + 50:
ball.setx(330)
ball.dx *= -1elif -340 < ball.xcor() < -330and paddle_a.ycor() - 50 < ball.ycor() < paddle_a.ycor() + 50:
ball.setx(-330)
ball.dx *= -1
screen.update()
screen.ontimer(single_step)
screen = Screen()
screen.title('Pong')
screen.bgcolor('black')
screen.setup(width=800, height=600)
screen.tracer(0)
# paddle A
paddle_a = Turtle()
paddle_a.shape('square')
paddle_a.color('white')
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.penup()
paddle_a.setx(-350)
# paddle B
paddle_b = Turtle()
paddle_b.shape('square')
paddle_b.color('white')
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.penup()
paddle_b.setx(350)
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.dx = 1
ball.dy = 1# pen
pen = Turtle()
pen.hideturtle()
pen.color('white')
pen.penup()
pen.sety(260)
pen.write("Player A: 0 Player B: 0", align='center', font=FONT)
# Keyboard binding
screen.onkeypress(paddle_a_up, 'w')
screen.onkeypress(paddle_a_down, 's')
screen.onkeypress(paddle_b_up, 'Up')
screen.onkeypress(paddle_b_down, 'Down')
screen.listen()
single_step()
screen.mainloop()
Now when you close the window, that event will be handled by the same mainloop
event handler that's running your game.
Post a Comment for "Python Returns An Error When I Try To Quit The Application Window"