What is the simplest way to get monitor resolution (preferably in a tuple)?
On Windows 8.1 I am not getting the correct resolution from either ctypes or tk. Other people are having this same problem for ctypes: getsystemmetrics returns wrong screen size To get the correct full resolution of a high DPI monitor on windows 8.1, one must call SetProcessDPIAware and use the following code:
import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
Full Details Below:
I found out that this is because windows is reporting a scaled resolution. It appears that python is by default a 'system dpi aware' application. Types of DPI aware applications are listed here: http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx#dpi_and_the_desktop_scaling_factor
Basically, rather than displaying content the full monitor resolution, which would make fonts tiny, the content is scaled up until the fonts are big enough.
On my monitor I get:
Physical resolution: 2560 x 1440 (220 DPI)
Reported python resolution: 1555 x 875 (158 DPI)
Per this windows site: http://msdn.microsoft.com/en-us/library/aa770067%28v=vs.85%29.aspx The formula for reported system effective resolution is: (reported_px*current_dpi)/(96 dpi) = physical_px
I'm able to get the correct full screen resolution, and current DPI with the below code. Note that I call SetProcessDPIAware() to allow the program to see the real resolution.
import tkinter as tk
root = tk.Tk()
width_px = root.winfo_screenwidth()
height_px = root.winfo_screenheight()
width_mm = root.winfo_screenmmwidth()
height_mm = root.winfo_screenmmheight()
# 2.54 cm = in
width_in = width_mm / 25.4
height_in = height_mm / 25.4
width_dpi = width_px/width_in
height_dpi = height_px/height_in
print('Width: %i px, Height: %i px' % (width_px, height_px))
print('Width: %i mm, Height: %i mm' % (width_mm, height_mm))
print('Width: %f in, Height: %f in' % (width_in, height_in))
print('Width: %f dpi, Height: %f dpi' % (width_dpi, height_dpi))
import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
print('Size is %f %f' % (w, h))
curr_dpi = w*96/width_px
print('Current DPI is %f' % (curr_dpi))
Which returned:
Width: 1555 px, Height: 875 px
Width: 411 mm, Height: 232 mm
Width: 16.181102 in, Height: 9.133858 in
Width: 96.099757 dpi, Height: 95.797414 dpi
Size is 2560.000000 1440.000000
Current DPI is 158.045016
I am running windows 8.1 with a 220 DPI capable monitor. My display scaling sets my current DPI to 158.
I'll use the 158 to make sure my matplotlib plots are the right size with: from pylab import rcParams rcParams['figure.dpi'] = curr_dpi
If you are using the Qt
toolkit specifically PySide
, you can do the following:
from PySide import QtGui
import sys
app = QtGui.QApplication(sys.argv)
screen_rect = app.desktop().screenGeometry()
width, height = screen_rect.width(), screen_rect.height()
Expanding on @user2366975's answer, to get the current screen size in a multi-screen setup using Tkinter (code in Python 2/3):
try:
# for Python 3
import tkinter as tk
except ImportError:
# for Python 2
import Tkinter as tk
def get_curr_screen_geometry():
"""
Workaround to get the size of the current screen in a multi-screen setup.
Returns:
geometry (str): The standard Tk geometry string.
[width]x[height]+[left]+[top]
"""
root = tk.Tk()
root.update_idletasks()
root.attributes('-fullscreen', True)
root.state('iconic')
geometry = root.winfo_geometry()
root.destroy()
return geometry
(Should work cross-platform, tested on Linux only)
Using Linux Instead of regexp take the first line and take out the current resolution values.
Current resolution of display :0
>>> screen = os.popen("xrandr -q -d :0").readlines()[0]
>>> print screen
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 1920 x 1920
>>> width = screen.split()[7]
>>> print width
1920
>>> height = screen.split()[9][:-1]
>>> print height
1080
>>> print "Current resolution is %s x %s" % (width,height)
Current resolution is 1920 x 1080
This was done on xrandr 1.3.5, I don't know if the output is different on other versions, but this should make it easy to figure out.
Using pygame:
import pygame
pygame.init()
infos = pygame.display.Info()
screen_size = (infos.current_w, infos.current_h)
[1]
However, if you're trying to set your window to the size of the screen, you might just want to do:
pygame.display.set_mode((0,0),pygame.FULLSCREEN)
to set your display to fullscreen mode. [2]
I created a PyPI module for this reason:
pip install screeninfo
The code:
from screeninfo import get_monitors
for m in get_monitors():
print(str(m))
Result:
monitor(1920x1080+1920+0)
monitor(1920x1080+0+0)
It supports multi monitor environments. Its goal is to be cross platform; for now it supports Cygwin and X11 but pull requests are totally welcome.