Conrad Selig
Conrad Selig

Reputation: 401

Tab out of Pygame fullscreen window without crashing it

So I'm using Pygame to create a fancy display for a program I am writing. I chose Pygame because it's easy to get started and does a great job with animations. I want the display to be as big as I can make it so as much information can be shown as possible. Here is the kicker however, I still want to be able to get to the console of the program.

Pygame forces a fullscreen window to the front, so you cant tab out, and moving the windows to another windows desktop crashes the display. I would do a key trick to switch the pygame mode, but I cannot use pygame.event.get() because of how the program the threaded.

Is there a way to make it a full-screen window so that I can tab out and leave it up in the background? I dont really want it to just be a normal window because it is not as big that way.

The display crashes after I tab out and back in, here is what that looks like: enter image description here I also get a non-zero exit code: -805306369 (0xCFFFFFFF)

Here is a broken down version of the code that still gives me this error, you'll notice there are some things in here you wouldn't have if this was your full program, but I wanted to retain as much architecture as I could.

import pygame
import os

BACKGROUND = (9, 17, 27)

os.environ['SDL_VIDEO_WINDOW_POS'] = "0,0"
pygame.init()
pygame.font.init()

infoObject = pygame.display.Info()
SIZE = (infoObject.current_w, infoObject.current_h)
X_CENTER = SIZE[0]/2
Y_CENTER = SIZE[1]/2

# create a borderless window that's as big as the entire screen
SCREEN = pygame.display.set_mode((SIZE[0], SIZE[1]), pygame.NOFRAME)
clock = pygame.time.Clock()

TextFont = pygame.font.SysFont('Courant', 30)


class DisplayState:

    state = type(bool)

    def __init__(self):
        self.state = True

    def get_state(self):
        return self.state

    def change_state(self, new_state):
        self.state = new_state


def main(display_state_object):

    running = True

    while running:
        if display_state_object.get_state():
            SCREEN.fill(BACKGROUND)
            pygame.display.flip()
        else:
            return 1
    return

if __name__ == "__main__":
    main(DisplayState())

EDIT

I think it is a multi-threading problem! See this code:

Produces Error

def start_display():
     display(params)

def display(params):
     pygame loop

if __name__ == "__main__":
     display_thread = threading.Thread(target=start_display)
     display_thread.start()

Does not produce error

def display(params):
     pygame loop

if __name__ == "__main__":
     display_thread = threading.Thread(target=display(params))
     display_thread.start
     # marker

One problem with the version that does work, the program does not seem to be continuing forwards outside the thread (ie the marker is never reached). Is this how the threading library works? It may explain why I had the middle man function present. Maybe this is a different problem and deserves its own question?

EDIT

Setting up the thread like this allows the main thread to continue, but brings back the pygame error:

threading.Thread(target=display, args=(DisplayState(),))

Upvotes: 4

Views: 1408

Answers (2)

skrx
skrx

Reputation: 20438

You have to call one of the pygame event functions (e.g. pygame.event.pump() or pygame.event.get()) each frame or the window will become unresponsive and the program will appear to have crashed. If you call one of those functions, you should be able to press Alt+Tab (in Windows) to get back to the desktop without crashing the program (if you select the desktop, the window will be minimized and if you select another window, it will just be brought to the front).

def main(display_state_object):

    running = True

    while running:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                # Press Esc to quit.
                if event.key == pygame.K_ESCAPE:
                    running = False

        if display_state_object.get_state():
            SCREEN.fill(BACKGROUND)
            pygame.display.flip()
        else:
            return 1
    return

Upvotes: 1

sloth
sloth

Reputation: 101072

There's no easy way to do this on windows/sdl using the real fullscreen mode, and the usual way to solve this is to use a borderless window.

Here's how to create such a "fake" fullscreen window in pygame:

import pygame
import os  

# you can control the starting position of the window with the SDL_VIDEO_WINDOW_POS variable
os.environ['SDL_VIDEO_WINDOW_POS'] = "0,0"
pygame.init()

# now let's see how big our screen is
info = pygame.display.Info()

# and create a borderless window that's as big as the entire screen
screen = pygame.display.set_mode((info.current_w, info.current_h), pygame.NOFRAME)

Upvotes: 3

Related Questions