Python Forum
[PyGame] pygame in Backgroundthread works in Linux, crashes in Win10
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] pygame in Backgroundthread works in Linux, crashes in Win10
#1
Dear all,

I am working on a project where pygame is running in a background tread to provide a GUI and the main program is interacting indirectly with pygame. For this project it is absolutely crucial that pygame is not mentioned in the main loop. A rather striped down example would look like this:

import pygame
import threading
import time


class cbg_pygame(threading.Thread):
    """
        Main class emulating the GPIO and i2c and draws the main window.
    """
    def __init__(self, xoffset = 150, yoffset = 20):
        
        threading.Thread.__init__(self)
                
        # Initialise pygame and create screen, surfaces and Gadgets (Input/Buttons/Lists...)    
        pygame.init()
        
        # Define some colors
        self.pos=[0,0] #Position of the ball on the screen
        self.dimension=[800,600] #screen dimensions
        self.size=30 #size of the ball

        self._screen = pygame.display.set_mode((self.dimension[0], self.dimension[1]))
                
        pygame.display.set_caption('pygames-test')
        
        
        #load the background image
        pygame.mouse.set_visible(1)
        pygame.key.set_repeat(1, 30)
        
        
    def run(self): 
        """
            Mainloop of the emulated GPIO. Is called when the emulator class is initialized.
        """
        
        self.running = True
    
        # create clock to reduce framerate
        clock = pygame.time.Clock()
        
        while self.running:
            clock.tick(30) #reduce framerate to 30 fps
    
            # get all events and check them 
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    self.running = False
                
            self._screen.fill((255, 255, 255))
            pygame.draw.ellipse(self._screen, (0, 0, 0), [self.pos[0], self.pos[1], self.size, self.size], 4)
            pygame.display.flip()

        pygame.quit()
        
    def stop(self):
        self.running = False

bgpg = cbg_pygame()
bgpg.start()

direction=[1,1]
while(bgpg.running): #Program is stopped if pygame window is closed
    for i in range(2):
        if direction[i]: #direction[0]=x, direction[1]=y, traveling with a velocity of 20 pixels/circle
            if bgpg.pos[i]+20 < bgpg.dimension[i]-bgpg.size:
                bgpg.pos[i]=bgpg.pos[i]+20
            else:
                bgpg.pos[i]=bgpg.dimension[i]-bgpg.size
                direction[i]=0
        else:
            if bgpg.pos[i]-20 > 0:
                bgpg.pos[i]=bgpg.pos[i]-20
            else:
                bgpg.pos[i]=0
                direction[i]=1
                
    time.sleep(0.1)
I know this example makes no sense but it demonstrates what I need to achieve. There is a main loop controlling some stuff in a class and pygame is running in the background to display the data in some form.

This example runs absolutely fine on Linux but crashes on Windows 10. I assume this is caused by the two loops running in parallel, while only one is handling the pygame (Windows) events. Maybe threading is not the right approach here, but as I am not very experienced in multiprocessing and Co I am totally lost. Would someone be able to help? Thanks a lot in advance.
Reply
#2
I don't think you need to use threading for this. In cbg_pygame.run you can take out the while loop, then move the couple lines of code before it into cbg_python.__init__. In the main loop you can execute the run function and then perform the tasks you need to. Also the time.sleep on line 79 will have to be taken out. You can instead use some kinda of debounce with time, here's an example:
import time

debounce = False
secondsCount = 0
loopCount = 0

running = True
timeRecorded = time.time()
while running:
    loopCount += 1
    if time.time()-timeRecorded >= 1:
        secondsCount+=1
        print(f"Seconds passed: {secondsCount}")
    if secondsCount == 5:
        running = False
print(f"Loop finished after {secondsCount} seconds with {loopCount} loops")
Threading can slow down a program by quite a bit, so I don't think this method would slow it down and if it does then not by much. You could also focus on how to make the code run more efficiently to not get any lag. Hopefully this helps
Reply
#3
Hi,
you are right, it is not relevant for this particular example to work with two independent loops. However, this example is completely artificial to illustrate the problem.

What I need to realize is that all the pygame stuff runs in the background while the programmer only interacts with the class provided. The reason for that is that I am working on a small emulator to emulate the hardware pins of a Raspberry Pi. The basic idea is to provide a package coming with the same classes as the Raspberry pakage for interacting with the hardware. However, instead of forwarding the user input to the Raspberry's Hardware it is forwarded to the pygame interface to provide a graphical representation of what would happen if you run that code on your Raspberry. This gives you the freedom to test your code on a regular computer. Full project can be found here: https://github.com/blbltheworm/yarpie
Reply
#4
I took a quick 20 minute read through the git project to try and get the gist of how all the class work together and I think I understand it for the most part. If the threading is crashing the program, then the best solution I can think of is having a single function that the programmer needs to initiate in some kind of loop as they are using the gui. That function can update the gui and do what it needs to instead of having a thread constantly running in the background. Sorry if this isn't helpful, it's the only solution that came to mind. I wish you luck with your project.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  pygame exe crashes TheQuattro 1 2,450 Jan-26-2019, 11:28 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020