Pyglet window does not reopen after being run - python

I made a Snake game program and I've made a function called Starting_screen() that opens a window with labels and sprites that shows the starting menu of the game where the player can choose to start a new game, check the leader board, or quit the game.
My main problem is that after the player finishes a game of Snake, I want the program to return to the main menu but it just hangs after the game exits. I've tried putting print statements within the Starting_Screen() function and it actually prints twice, indicating that it re-enters the function but does not open the window again. The flow of the program looks somewhat like this (in simpler sense):
The game is being run by main.py that has:
import interface
import engine
interface.main()
print('outside the interface.main()')
interface.main()
As you can see I've just initially tried to put two interface.main() functions so that I can check if the program runs the second one. It actually prints the statement which indicates it exits the function.
The interface.main() runs only the Starting_screen(), and the Starting_screen() looks like this (simplified):
def Starting_screen():
print('inside starting screen')
window = pyglet.window.Window()
some_text = pyglet.text.Label()
some_image = pyglet.image.load()
#window.event
def on_draw():
window.clear()
some_text.draw()
some_image.draw()
#window.event
def on_key_press(symbol,modifier):
if symbol == key.P:
window.close()
engine.main()
pyglet.app.run()
and the engine.main() just runs the game (using pygame) until the player loses and it will pygame.display.quit() that will terminate the engine.main() function and returns to the Starting_screen() which in turn terminates the function.
I was hoping it would open the main menu window again but it does not. But interestingly enough, it runs print('inside starting screen') twice, indicating that it runs the function again, but it does not open the window like what would normally happen when it was run for the first time.
Any suggestions would be appreciated.

Related

Which code does the mainloop() processes infinitely until any event occurs?

To understand my question kindly follow the paragraphs written below:
What code does the mainloop processes infinitely? Like does it read the code of the entire program again and again?
consider the code:
from tkinter import *
window = Tk()
print("lol")
print("Hello World")
window.mainloop()
the output didn't print "Hello World" or "lol" infinite number of times, so the mainloop() doesn't loop the code of the current module.
Now consider this code:
from tkinter import *
print("lol")
window = Tk()
print("Hello World")
while True:
window.update()
Now, even this code executes the same output, so now we can consider the mainloop() loops the code "window.update()" infite number of times, but more efficiently(somehow).
Now the first question arises what does the window.update() function do to update the values in the GUI, does it re-read the code from top to bottom again, or how does the update function update the GUI widget vaules.
The second question is :
I read this article
"Mainloop in Python Tkinter is an infinite loop of the application window which runs forever so that we can see the still screen.
The application window is like a frame that keeps on destroying every microsecond but the main loop keeps on creating a new updated window.
This process of destroying old window screens and creating a new one happens so fast that human eyes don’t even realize it.
Since the process runs infinite time that is why we are able to see the application in front of us and when we close the window then the loop terminates or exits."
Now if this is true then to recreate an updated window the root.mainloop() must read the entire root GUI code again and again entirely or is there another explanation to it.
I have been trying to understand this for the past 6hrs and I have visited every site and I cannot find the solution for the life of me.
Regards,
Rashik
What code does the mainloop processes infinitely? Like does it read the code of the entire program again and again?
No.
Via this function, it calls this C code which has the embedded Tcl interpreter process one event, or wait for Tkinter_busywaitinterval before trying to process another event
Now, even this code executes the same output, so now we can consider the mainloop() loops the code "window.update()" infite number of times, but more efficiently(somehow).
window.update() calls TCL update, which is described to
[...] bring the application “up to date” by entering the event loop repeatedly until all pending events (including idle callbacks) have been processed.
Your infinite loop doesn't have a sleep, so it's spinning your CPU as hard as possible to do practically nothing.
[...] Does it re-read the code from top to bottom again, or how does the update function update the GUI widget vaules.
It certainly doesn't re-read your code. It processes any pending widget updates, which may have happened by running e.g. window.text("...") in e.g. a click callback or an .after() timeout, etc.
I read this article [...]
That article seems wrong and/or at least over-simplifies things.
This simple example clock should clarify how things work:
import time
import tkinter as tk
root = tk.Tk()
text = tk.Label(root)
text.pack()
def tick():
text["text"] = time.ctime() # update `text` widget's content
root.after(1000, tick) # schedule for this function to be called after 1 second
if __name__ == '__main__':
tick() # call the `tick` function once before entering main loop
root.mainloop()

I get errors when I click the turtle game exit (X) button

Gets error when I click the exit (X) button:
Failed to execute script pong
How can I close the turtle game by clicking the exit button with no error?
Getting errors from turtle when you close the window is highly indicative of not playing by the rules event-wise. Typically it's due to a while True: loop instead of using timer events. A properly event-drive turtle program should reach the mainloop statement (or one of its equivalents) and allow events to run the show. If you want specifics, provide your code as part of your question.
The error in the terminal must be due to the the while True: loop that most beginners like me use. Closing the window abruptly stops the process while the while True: loop was still going on. So, in order to avoid this error you can define a function
#Function
def quit():
global running
running = False
#Keybinding
screen.onkeypress(quit, "q")
#Main game loop
while running:
...
#update events
...

Problem with using keyboard module and turtle together

I am writing a script to read my keystrokes and draw simple shapes in turtle.
To record keystrokes, I am using the keyboard module and I am using turtle for drawing.
I am getting struck due to the use of threading in the keyboard module.
What I am currently doing is-
I added hotkeys using keyboard.add_hotkey method.
If I am pressing a certain key, that letter is added to a list (named data) for later use.
When I press the combination of Ctrl+Shift+S, the save function is called. In the save function, a turtle window is instantiated, and the list data is popped one letter at a time. The shape is drawn according to the letter popped.
When the list gets empty, I save the drawing and close the turtle window.
The problem that I am facing is that once the save function is called, the program stops listening to other calls. It is perhaps due to the use of threads in keyboard module.
The code is attached here-
def start():
#turtle.mainloop()
s=turtle.Screen().setup( width = WIDTH, height = HEIGHT, startx = 0, starty = 0)
global t
t=turtle.Turtle()
turtle.ht()
t.ht()
def save():
start()
global t
global data
t.speed(0)
while data:
fun = data.pop()
if fun=='c':
draw_circle()
elif fun=='r':
draw_rectangle()
elif fun=='p':
draw_polygon()
elif fun=='h':
draw_hexagon()
elif fun=='t':
draw_triangle()
elif fun=='m':
draw_pentagon()
ts = turtle.getscreen()
ts.getcanvas().postscript(file="drawing.eps")
img = Image.open('drawing.eps')
img.save('drawing.png')
turtle.bye()
def push_fun(fun):
data.append(fun)
if __name__=='__main__':
keyboard.add_hotkey('ctrl+shift+s', save)
keyboard.add_hotkey('ctrl+shift+e', exit)
keyboard.add_hotkey('ctrl+shift+p', send_to_server)
# keyboard.add_hotkey('ctrl+shift+s', save, args=(data))
keyboard.add_hotkey('c', push_fun, args=('c',))
keyboard.add_hotkey('s', push_fun, args=('t',))
keyboard.add_hotkey('h', push_fun, args=('h',))
keyboard.add_hotkey('p', push_fun, args=('p',))
keyboard.add_hotkey('r', push_fun, args=('r',))
keyboard.wait()
After the save function is called, the program remains in the keyboard.wait() part but does not listen to any other key press.
you can end the wait by setting a key to press like:
keyboard.wait('space')
but keyboard.wait() without any keys given blocks all keystrokes forever
I'm not sure why you even put it there, I'm not even sure why it picks anything up at all, but I think you can do this:
if __name__=='__main__':
'''your keystrokes'''
while True: #or set a timer or something
pass
you didn't give me the whole code so I can't make sure it works
you also need to global the list data in the push_fun function
I hope it helps :)

My turtle program in python acts like it has been clicked

import turtle
window = turtle.Screen()
pen = turtle.Turtle()
def star():
pen.forward(100);
turtle.onscreenclick(star())
window.mainloop()
I am very new to turtle,and python itself, I am just using some of the documentation that I found on the python website, but when I run this program it runs my function star without the screen even being clicked. The end goal of this program would be for me to click then it would run the function, then if I clicked again the screen would clear and the function would be run again.
Thanks for the help!
You need to pass reference to start function into onscreenclick, and make start to accept two arguments:
def star(x,y):
pen.forward(100);
turtle.onscreenclick(star)

PlaySound() slows down process

I have the following code in my program:
self["text"]="✖"
self["bg"]="red"
self["relief"] = SUNKEN
self.banged = True
self.lost = True
self.lettersLeft = 0
self.lettersBanged = self.lettB
winsound.PlaySound('sound.wav', winsound.SND_FILENAME)
messagebox.showerror("Letter Banging","Sorry, you lost the game!", parent=self)
for key in self.squares.keys():
if self.squares[key].value == 3:
self.squares[key].banged = False
self.squares[key].expose()
I have just added the winsound.PlaySound('sound.wav', winsound.SND_FILENAME) part and it has slowed down my program. Infact, it plays the sound first and then does what is before it. I am using Python with tKinter. Any suggestions?
When you alter the property of a widget, such as editing content, background and relief, this change does not appear immediately, they are recorded, and only take effect when you give hand to the mainloop which provoke redraw of your application. This lead to the behavior you observed: the sound is played, then the callback ends and the redraw showing your change happens.
All the time that you will spend in a callback playing the sound, your application will be not responsive. If you estimate your sound is short enough, you can add self.update() somewhere between the UI change you want to show first and the call to PlaySound.
If you want to avoid any unresponsiveness in your app, you can play the sound in another thread
sound_thread = threading.Thread(target=lambda:winsound.PlaySound('sound.wav', winsound.SND_FILENAME))
sound_thread.start()

Categories