I need the window position right after I created a pygame window:
window = pygame.display.set_mode((width, height), 0, 32)
pygame.init()
By default, the window starts at 0,0 - but I also need x,y if the user changes the window position. Any ideas?
I need x,y coords of the pygame window - either at start or on window move. The last one is nice to have.
I figured out how to center the pygame window at the bottom of the screen:
pos_x = screen_width / 2 - window_width / 2
pos_y = screen_height - window_height
os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (pos_x,pos_y)
os.environ['SDL_VIDEO_CENTERED'] = '0'
Background: I have x,y coords which are screen related and I must convert the screen coords into window-local coords so that I can use them e.g. to display coords inside the pygame window or to discard coords which are outside the pygame window.
With my approach above, I knwo the initial position. But I can only use a single pygame window (because it's always at the same position) and things go wrong if the user moves the window.
It have worked for me :
import os
import pygame
x = 100
y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
pygame.init()
screen = pygame.display.set_mode((100,100))
Taken from https://www.pygame.org/wiki/SettingWindowPosition
Here is an example code that return all four corner positions:
from ctypes import POINTER, WINFUNCTYPE, windll
from ctypes.wintypes import BOOL, HWND, RECT
# get our window ID:
hwnd = pygame.display.get_wm_info()["window"]
# Jump through all the ctypes hoops:
prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
paramflags = (1, "hwnd"), (2, "lprect")
GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
# finally get our data!
rect = GetWindowRect(hwnd)
print "top, left, bottom, right: ", rect.top, rect.left, rect.bottom, rect.right
# bottom, top, left, right: 644 98 124 644
There is a pygame.display.get_wm_info() call that gets you the Window handler -- from then on, it is using either X11 or Windows API32 to get information from the window through this handler. I didn't find any readily available information on how to do that.
So, just to be clear: there is no ordinary way to do that from within pygame. You have to proceed with another library, possibly using ctypes, after you get the window handler.
On the other hand, if you have to manipulate the window itself, maybe pygame is not the most suitable library for you to use -- you could try PyQt or even GTK+ - they also provide multmedia facilites while being more proper to operate on the level of GUI Windows and other controls
update There are ways to setup an OpenGL backend for pygame graphics, that will allow complete control of the display - including embedding it in another window, as part of a tkinter or Qt application. People that are interested can search a little deeper along those lines.
In Pygame 2, you can alternatively import the _sdl2.video to set the window position. Note that this module is experimental and could be changed in future versions.
import pygame
from pygame._sdl2.video import Window
pygame.init()
window = Window.from_display_module()
window.position = your_position_tuple
Using environment variables as mentioned in other answers is sufficient for most cases, but the downside is that once you have change the window position it will not work a second time (at least in Pygame 2).
Pygame is based on Simple DirectMedia Layer (SDL). Hence you can set SDL environment variables.
See pygame wiki - SettingWindowPosition:
You can set the position of the window by using SDL environment variables before you initialise pygame. Environment variables can be set with the os.environ dict in python.
x = 100
y = 0
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
import pygame
pygame.init()
screen = pygame.display.set_mode((100,100))
(0,0) remains the upper left corner whether the window is moved or not. If you're trying to make (0,0) stay physically where it was on the screen when the window initialized, I don't think pygame can do that. Try to make your question clearer if you want clearer answers.
To accomplish this where you don't know the monitor size of the user, use screeninfo in addition to the pygame and os packages. Screeninfo is OS-agnostic, meaning you can get the resolution of all monitors regardless of a users operating system.
import pygame
from screeninfo import get_monitors
import os
# Set the size of the pygame window
window_width = 512
window_height = 288
window_size = (window_width, window_height)
# Get the bounds of the users monitors, and select the first one
monitors = get_monitors() # Get the resolution of all of the users monitors
screen_width = monitors[0].width # Get width of first monitor found
screen_height = monitors[0].height # Get height of first monitor found
# Set the x and y coordinates of the pygame window in relation to the monitor's resolution
# (I wanted my pygame window to be located in the bottom-right of the monitor)
pos_x = screen_width - window_width # Calculate the x-location
pos_y = screen_height - window_height # Calculate the y-location
os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (pos_x,pos_y) # Set pygame window location
pygame.init() # Initialize the pygame window
self.screen = pygame.display.set_mode(size) # Set the location of the pygame window
Related
I need the window position right after I created a pygame window:
window = pygame.display.set_mode((width, height), 0, 32)
pygame.init()
By default, the window starts at 0,0 - but I also need x,y if the user changes the window position. Any ideas?
I need x,y coords of the pygame window - either at start or on window move. The last one is nice to have.
I figured out how to center the pygame window at the bottom of the screen:
pos_x = screen_width / 2 - window_width / 2
pos_y = screen_height - window_height
os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (pos_x,pos_y)
os.environ['SDL_VIDEO_CENTERED'] = '0'
Background: I have x,y coords which are screen related and I must convert the screen coords into window-local coords so that I can use them e.g. to display coords inside the pygame window or to discard coords which are outside the pygame window.
With my approach above, I knwo the initial position. But I can only use a single pygame window (because it's always at the same position) and things go wrong if the user moves the window.
It have worked for me :
import os
import pygame
x = 100
y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
pygame.init()
screen = pygame.display.set_mode((100,100))
Taken from https://www.pygame.org/wiki/SettingWindowPosition
Here is an example code that return all four corner positions:
from ctypes import POINTER, WINFUNCTYPE, windll
from ctypes.wintypes import BOOL, HWND, RECT
# get our window ID:
hwnd = pygame.display.get_wm_info()["window"]
# Jump through all the ctypes hoops:
prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
paramflags = (1, "hwnd"), (2, "lprect")
GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
# finally get our data!
rect = GetWindowRect(hwnd)
print "top, left, bottom, right: ", rect.top, rect.left, rect.bottom, rect.right
# bottom, top, left, right: 644 98 124 644
There is a pygame.display.get_wm_info() call that gets you the Window handler -- from then on, it is using either X11 or Windows API32 to get information from the window through this handler. I didn't find any readily available information on how to do that.
So, just to be clear: there is no ordinary way to do that from within pygame. You have to proceed with another library, possibly using ctypes, after you get the window handler.
On the other hand, if you have to manipulate the window itself, maybe pygame is not the most suitable library for you to use -- you could try PyQt or even GTK+ - they also provide multmedia facilites while being more proper to operate on the level of GUI Windows and other controls
update There are ways to setup an OpenGL backend for pygame graphics, that will allow complete control of the display - including embedding it in another window, as part of a tkinter or Qt application. People that are interested can search a little deeper along those lines.
In Pygame 2, you can alternatively import the _sdl2.video to set the window position. Note that this module is experimental and could be changed in future versions.
import pygame
from pygame._sdl2.video import Window
pygame.init()
window = Window.from_display_module()
window.position = your_position_tuple
Using environment variables as mentioned in other answers is sufficient for most cases, but the downside is that once you have change the window position it will not work a second time (at least in Pygame 2).
Pygame is based on Simple DirectMedia Layer (SDL). Hence you can set SDL environment variables.
See pygame wiki - SettingWindowPosition:
You can set the position of the window by using SDL environment variables before you initialise pygame. Environment variables can be set with the os.environ dict in python.
x = 100
y = 0
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
import pygame
pygame.init()
screen = pygame.display.set_mode((100,100))
(0,0) remains the upper left corner whether the window is moved or not. If you're trying to make (0,0) stay physically where it was on the screen when the window initialized, I don't think pygame can do that. Try to make your question clearer if you want clearer answers.
To accomplish this where you don't know the monitor size of the user, use screeninfo in addition to the pygame and os packages. Screeninfo is OS-agnostic, meaning you can get the resolution of all monitors regardless of a users operating system.
import pygame
from screeninfo import get_monitors
import os
# Set the size of the pygame window
window_width = 512
window_height = 288
window_size = (window_width, window_height)
# Get the bounds of the users monitors, and select the first one
monitors = get_monitors() # Get the resolution of all of the users monitors
screen_width = monitors[0].width # Get width of first monitor found
screen_height = monitors[0].height # Get height of first monitor found
# Set the x and y coordinates of the pygame window in relation to the monitor's resolution
# (I wanted my pygame window to be located in the bottom-right of the monitor)
pos_x = screen_width - window_width # Calculate the x-location
pos_y = screen_height - window_height # Calculate the y-location
os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (pos_x,pos_y) # Set pygame window location
pygame.init() # Initialize the pygame window
self.screen = pygame.display.set_mode(size) # Set the location of the pygame window
In turtle, I am interested in finding out the canvas dimensions once my main window has "maximized".
The code for creating and maximizing a turtle window is:
def make_window2():
canvas = t.getcanvas()
root = canvas.winfo_toplevel()
root.title("Serpenski")
root.state('zoomed')
return root, canvas, t
where t is the imported turtle object (i.e import turtle as t)
Issue happens when I try to use it.
window, canvas, turtle = make_window2()
screen = turtle.Screen()
win_width = screen.window_width()
win_height = screen.window_height()
print((win_width, win_height))
time.sleep(10) #waiting 10 seconds
win_width = screen.window_width()
win_height = screen.window_height()
print((win_width, win_height)) # Prints the same thing as before...
I ran my script in the interpreter mode (passing -i switch to python binary). During time.sleep(10), if you happen to see turtle window, you'd see that the resize operation is in progress and it hangs until the next interpreter prompt is shown (i.e. when the above bit of code completes executing). Please note, that the resize operation completes after this code execution is over.
So how to run the above code after the root window has maximized?
PS: using python 3.10.2, on windows 11 machine.
Not sure if it is a soluiton. After some hacking around, I found that turtle.reset() does the trick.
I am just setting up some functions for my game but my script fails to load the image
#used variables
# x, y for alien location
# nPc for the aliens image
#
#
#
#
#
#
#
#
#
#
#set up
import pygame, sys, random, time, math
from pygame.locals import *
pygame.init()
nPc = '/home/claude/Dropbox/Bowtie/Prisim/Images/Alien_Races/Standered/alien_1.png'
nPc = pygame.image.load(nPc).convert_alpha()
def loc_alien():
x = random.randint(0, 400)
y = randaom.randint(0, 400)
def spawn_alien(x, y):
screen.blit(nPc, (x, y))
when I run this I wont nothing to happen as I am not using the functions yet, but when I do run it I get this error
Traceback (most recent call last):
File "/home/claude/Dropbox/Bowtie/Prisim/Scripts/aliens.py", line 26, in <module>
nPc = pygame.image.load(nPc).convert_alpha()
error: No video mode has been set
anyone know what I'm doing wrong?
I believe that you need to call:
screen = pygame.display.set_mode((800, 600)) # change to the real resolution
this call will actually return the surface that you want to blit on. Below is the documentation from the linked resource.
pygame.display.set_mode()
Initialize a window or screen for display
set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
This function will create a display Surface. The arguments passed in
are requests for a display type. The actual created display will be
the best possible match supported by the system.
The resolution argument is a pair of numbers representing the width
and height. The flags argument is a collection of additional options.
The depth argument represents the number of bits to use for color.
The Surface that gets returned can be drawn to like a regular Surface
but changes will eventually be seen on the monitor.
If no resolution is passed or is set to (0, 0) and pygame uses SDL
version 1.2.10 or above, the created Surface will have the same size
as the current screen resolution. If only the width or height are set
to 0, the Surface will have the same width or height as the screen
resolution. Using a SDL version prior to 1.2.10 will raise an
exception.
It is usually best to not pass the depth argument. It will default to
the best and fastest color depth for the system. If your game requires
a specific color format you can control the depth with this argument.
Pygame will emulate an unavailable color depth which can be slow.
When requesting fullscreen display modes, sometimes an exact match for
the requested resolution cannot be made. In these situations pygame
will select the closest compatible match. The returned surface will
still always match the requested resolution.
The flags argument controls which type of display you want. There are
several to choose from, and you can even combine multiple types using
the bitwise or operator, (the pipe “|” character). If you pass 0 or no
flags argument it will default to a software driven window. Here are
the display flags you will want to choose from:
pygame.FULLSCREEN create a fullscreen display
pygame.DOUBLEBUF recommended for HWSURFACE or OPENGL
pygame.HWSURFACE hardware accelerated, only in FULLSCREEN
pygame.OPENGL create an OpenGL renderable display
pygame.RESIZABLE display window should be sizeable
pygame.NOFRAME display window will have no border or controls
For example:
# Open a window on the screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width,screen_height])
Do not forgot to create your surface before creating variables with images in it
like this:
win = pygame.display.set_mode((576, 1024))
background_day = pygame.image.load("background-day.png").convert()
not like this:
background_day = pygame.image.load("background-day.png").convert()
win = pygame.display.set_mode((576, 1024))
I am just setting up some functions for my game but my script fails to load the image
#used variables
# x, y for alien location
# nPc for the aliens image
#
#
#
#
#
#
#
#
#
#
#set up
import pygame, sys, random, time, math
from pygame.locals import *
pygame.init()
nPc = '/home/claude/Dropbox/Bowtie/Prisim/Images/Alien_Races/Standered/alien_1.png'
nPc = pygame.image.load(nPc).convert_alpha()
def loc_alien():
x = random.randint(0, 400)
y = randaom.randint(0, 400)
def spawn_alien(x, y):
screen.blit(nPc, (x, y))
when I run this I wont nothing to happen as I am not using the functions yet, but when I do run it I get this error
Traceback (most recent call last):
File "/home/claude/Dropbox/Bowtie/Prisim/Scripts/aliens.py", line 26, in <module>
nPc = pygame.image.load(nPc).convert_alpha()
error: No video mode has been set
anyone know what I'm doing wrong?
I believe that you need to call:
screen = pygame.display.set_mode((800, 600)) # change to the real resolution
this call will actually return the surface that you want to blit on. Below is the documentation from the linked resource.
pygame.display.set_mode()
Initialize a window or screen for display
set_mode(resolution=(0,0), flags=0, depth=0) -> Surface
This function will create a display Surface. The arguments passed in
are requests for a display type. The actual created display will be
the best possible match supported by the system.
The resolution argument is a pair of numbers representing the width
and height. The flags argument is a collection of additional options.
The depth argument represents the number of bits to use for color.
The Surface that gets returned can be drawn to like a regular Surface
but changes will eventually be seen on the monitor.
If no resolution is passed or is set to (0, 0) and pygame uses SDL
version 1.2.10 or above, the created Surface will have the same size
as the current screen resolution. If only the width or height are set
to 0, the Surface will have the same width or height as the screen
resolution. Using a SDL version prior to 1.2.10 will raise an
exception.
It is usually best to not pass the depth argument. It will default to
the best and fastest color depth for the system. If your game requires
a specific color format you can control the depth with this argument.
Pygame will emulate an unavailable color depth which can be slow.
When requesting fullscreen display modes, sometimes an exact match for
the requested resolution cannot be made. In these situations pygame
will select the closest compatible match. The returned surface will
still always match the requested resolution.
The flags argument controls which type of display you want. There are
several to choose from, and you can even combine multiple types using
the bitwise or operator, (the pipe “|” character). If you pass 0 or no
flags argument it will default to a software driven window. Here are
the display flags you will want to choose from:
pygame.FULLSCREEN create a fullscreen display
pygame.DOUBLEBUF recommended for HWSURFACE or OPENGL
pygame.HWSURFACE hardware accelerated, only in FULLSCREEN
pygame.OPENGL create an OpenGL renderable display
pygame.RESIZABLE display window should be sizeable
pygame.NOFRAME display window will have no border or controls
For example:
# Open a window on the screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width,screen_height])
Do not forgot to create your surface before creating variables with images in it
like this:
win = pygame.display.set_mode((576, 1024))
background_day = pygame.image.load("background-day.png").convert()
not like this:
background_day = pygame.image.load("background-day.png").convert()
win = pygame.display.set_mode((576, 1024))
I am using pygame to program a simple behavioral test. I'm running it on my macbook pro and have almost all the functionality working. However, during testing I'll have a second, external monitor that the subject sees and the laptop monitor. I'd like to have the game so up fullscreen on the external monitor and not on the laptop's monitor so that I can monitor performance. Currently, the start of the file looks something like:
#! /usr/bin/env python2.6
import pygame
import sys
stdscr = curses.initscr()
pygame.init()
screen = pygame.display.set_mode((1900, 1100), pygame.RESIZABLE)
I was thinking of starting the game in a resizable screen, but that OS X has problems resizing the window.
Pygame doesn't support two displays in a single pygame process(yet). See the question here and developer answer immediately after, where he says
Once SDL 1.3 is finished then pygame will get support for using multiple windows in the same process.
So, your options are:
Use multiple processes. Two pygame instances, each maximized on its own screen, communicating back and forth (you could use any of: the very cool python multiprocessing module, local TCP, pipes, writing/reading files, etc)
Set the same resolution on both of your displays, and create a large (wide) window that spans them with your information on one half and the user display on the other. Then manually place the window so that the user side is on their screen and yours is on the laptop screen. It's hacky, but might a better use of your time than engineering a better solution ("If it's studpid and it works, it ain't stupid" ;).
Use pyglet, which is similar to pygame and supports full screen windows: pyglet.window.Window(fullscreen=True, screens[1])
Good luck.
I do not know if you can do this in OS X, but this is worth mentioning for the Windows users out there, if you just want to have your program to run full screen on the second screen and you are on windows, just set the other screen as the main one.
The setting can be found under Rearrange Your Displays in settings.
So far for me anything that I can run on my main display can run this way, no need to change your code.
I did something silly but it works.
i get the number of monitors with get_monitors()
than i use SDL to change the pygame window's display position by adding to it the width of the smallest screen, to be sure that the window will be positionned in the second monitor.
from screeninfo import get_monitors
numberOfmonitors = 0
smallScreenWidth = 9999
for monitor in get_monitors():
#getting the smallest screen width
smallScreenWidth = min(smallScreenWidth, monitor.width)
numberOfmonitors += 1
if numberOfmonitors > 1:
x = smallScreenWidth
y = 0
#this will position the pygame window in the second monitor
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
#you can check with a small window
#screen = pygame.display.set_mode((100,100))
#or go full screen in second monitor
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
#if you want to do other tasks on the laptop (first monitor) while the pygame window is being displayed on the second monitor, you shoudn't use fullscreen but instead get the second monitor's width and heigh using monitor.width and monitor.height, and set the display mode like
screen = pygame.display.set_mode((width,height))
display = pyglet.canvas.get_display()
display = display.get_screens()
win = pyglet.window.Window(screen=display[1])
------------------------------------------------------
screen=display[Номер монитора]
------------------------------------------------------
display = pyglet.canvas.get_display()
display = display.get_screens()
print(display) # Все мониторы которые есть