How can I get the size of the actual display, without using event.dict['size']?
Suppose I have a game with two screens, 'Menu' and 'Game', both of them resizable.
To make all images scale, I use in the beginning in the main file:
window = pygame.display.set_mode(reso,pygame.RESIZABLE)
window_fake = window.copy()
and inside the loops of the two screens I blit all images on the fake window and blit that to scale on the display window:
window.blit(pygame.transform.scale(window_fake, reso_act),(0,0))
pygame.display.flip()
for event in pygame.event.get():
if event.type==pygame.VIDEORESIZE:
reso_act = event.dict['size']
Now all images scale along when resizing the display. However, when I go from 'Menu' to 'Game' after resizing it, I need the size of the actual display to use as my variable reso_act, because I again blit everything onto my fake window and scale that to the display window, however there is no VIDEORESIZEevent.
So now if I make the display smaller in 'Menu', then click start and draw 'Game', it will have the original resolution and half of the images are outside of the display.
I have tried the following, but they all give me the value of reso, the original unresized resolution:
window.get_size()
window_fake.get_size()
pygame.display.get_surface().get_size()
window.get_rect()
window_fake.get_rect()
Is there a way to get the real size of the display?
Or otherwise a smarter way to achieve what I want to do?
I now solved it by returning reso_act every time from all the functions for the different screens and also passing it as input for all those functions, so it remembers the setting.
It is not so elegant, but it works.
If someone knows how to get the actual size of the display I would still be interested to know though.
Related
I am making a game using python and pygame. I had a problem a few days ago that I needed to give my games a functionality of being resized and maintain the aspect ratio. Also everything on the screen is resized proportionately. And luckily I got a quick solution to create two different pygame surfaces. One is the screen visible to the user and the other is to manage the blitting functionality. Actually, fake screen has everything blitted and then it itself is blitted to the main screen by using
main_screen.blit((pygame.transform.scale(fake_screen, main_screen.get_rect().size), [0, 0]).
The main problem is that now since the MOUSEBUTTONDOWN events are getting triggered on the main screen and not on fake screen, But
the clicks are getting processed according to the fake screen. This means that when I click on a button after resizing, the button appears to be their but actually its at its respective position on the fake screen. This makes all the buttons loose their functionality after the VIDEORESIZE event. Can anyone help me out with this? I hope that I was able to explain.
Easy answer: use the pygame.SCALED display flag.
It resizes the main screen for you and the mouse events too, without your program needing to know anything about it. Documented on this page: https://www.pygame.org/docs/ref/mixer.html
Using this means you wouldn’t need to use a fake screen at all, or do anything at all with scaling on your end.
DIY answer:
If you still want to control the scaling yourself, you just have to scale the mouse events along with the screen. Like scale then the opposite way you scale the fake screen.
In your case it looks like that would involve dividing the mouse event x by the ratio between fakescreen width and screen width, and same with y (with heights ofc).
I got a very easy solution to this myself. I just after getting mouse x and y coordinates, changed them to proportionately corresponding points. With a simple math. I mean, if x coordinate is 15% of main screen width, then convert it to 15% of fake screen width. This way, the fake screen will get properly scaled coordinates. The mathematical equation can be as follows:-
mouse_x = mouse_x/(xd/100)
mouse_x *= 10
mouse_y = mouse_y/(yd/100)
mouse_y *= 6
Here xd and yd are width and height of the resizable main screen respectively. And 10 and 6 are 1% of 1000 and 600 which are the width and height of the fake screen.
This solved my problem and game is now working perfectly.
Thank You.
I am working on tiny program to capture screen print, I want to do it in a similar fashion that Win Snipping Tool is working. First I need to overlay all screens with a 50% opacity layer and then, using the mouse, draw a rectangle and read vertices coordinates. Honestly, I have no idea how to bite this. I tried with win32api / gui and it is great to get mouse coordinates, but still was unable to draw a rectangle. My idea (one of many) is to (using PIL / ImageGrab) take shots of both displays, put an overlay and print them as a full screen on all windows, but I failed while doing this. Other idea is to take img grab and create two new windows using BeeWare / Toga (that is GUI framework I am using) in full screen, but I was unable to find any method to open window on second display. Any ideas and hints will be greatly appreciated, I am really counting on you, as I feel I reached dead end.
Well,It is very easy to use tkinter.
Ok,It is the principle when I make my screenshot application:
User presses the button to start.
Make a new window whose width and height should full cover all the screens,and hide the title bar(If it is had to achieve,maybe use width=9999 and height=9999).
Take a screenshot of all the desktop(You can use ImageGrab.grab((),all_screens=True)) to do that.
Make the screenshot showed in a Canvas(I know that toga have this widget).
Start your mouse listener thread and save the position of pressed.
When user moves his mouse,create a rectangle(toga's Canvas have a function rect()).Maybe use this rect(pressed_x,pressed_y,move_x,move_y).And delete the last rectangle(Then it will always show only one rectangle).
When user released his mouse,save the position of released.And use ImageGrab.grab((pressed_x,pressed_y,released_x,released_y),all_screens=True) to crop the selected area.
If you want to show it in application interface.toga has a widget called ImageView.You can put the image in it.
Does anyone know how make this (saving a scrollview stitched together as a series of images about the height of the screen) a reality?
There is the save_to_png method for every widget, but this only saves the currently visible portion of the screen. I'm not sure how to scroll down automatically by the height of the screen, and of course it would be better if there was a simple method for saving all of a widget to image, even if not currently rendered on the screen.
Any pointers on how to go about this?
When using python and pygame: after loading the screen with the background image and blitting new objects (Text, circles, rectangles, etc.), is there a way to save the modified screen so as to be recalled later in the program? Specifically, I am setting the background and blitting new objects and would like to save the screen image with all of the blits in intact so it can be used later in the program as a new background upon which sprites can be manipulated. Any suggestions welcomed!
Blitting works both ways, meaning you can blit something onto the display screen, but you can also blit the screen onto another surface. So simply make a new surface the same size of your display surface and blit the screen onto that surface for later use.
found a solution and it works better than I expected:
after blitted my raw background onto my surface and then adding numerous circles, rectangles and text to make an image with multiple dial, gauges and labels I ran the following:
pygame.display.update()
window = pygame.display.set_mode((800,480),0,32)
pygame.image.save(TFT,"screen_update.jpg")
the new image is saved to disk(XDcard on my RPi2) as "screen_update.jpg"
then I simply change the name to "ANAL_update.jpg" and use that as the background on my next program run. I commented out all of the code used to create the rectangles, circles and labels and it works. I will add an selectable "update" routine to the program and move all of extra drawing and labelling to that routine to be used when I wish to change the layout of he background. I like the fact that the program creates a new updated file that just needs to be renamed for use and for copying the background to other machines.
note: This is working on my RaspberryPi 2B with HDMI output to a 42" HD tv for development, but it is intended to run on an RPi3B with he official RPi 7 inch TFT display. Thanks to all of you that responded and to the others who left pertinent code for previous questions similar to mine.
I want to set a window's size, and then be able to resize it while the program is running. I've been able to make the window large, but I can't resize it smaller than the original set size. For a different project, I would also like to know how to make it so the window is not resizable at all.
For the first question: Gtk.Window.resize(width, height) should work. If you use set_size_request(width, height), you cannot resize your window smaller than these values.
For the second question: Gtk.Window.set_resizable(False)