题 如何在Python中获得显示器分辨率?


获取监视器分辨率的最简单方法是什么(最好是在元组中)?


69
2018-06-27 23:39


起源


您使用的是特定的UI工具包吗? (例如GTK,wxPython,Tkinter等) - detly
随着 Tkinter 模块,你可以做到 这条路。它是标准Python库的一部分,适用于大多数Unix和Windows平台。 - martineau
有关常见UI的不同技术的详细概述,请参阅 这个链接 - ImportanceOfBeingErnest


答案:


在Windows上:

from win32api import GetSystemMetrics

print("Width =", GetSystemMetrics(0))
print("Height =", GetSystemMetrics(1))

如果您正在使用高分辨率屏幕,请确保您的python解释器是HIGHDPIAWARE。

基于 这个 帖子。


40
2018-06-27 23:41



有关多平台完整解决方案,请参阅此处 回答 - Dhruv Reshamwala
使用多个显示器时,这只会返回主显示器的大小。 - Steven Vascellaro


在Windows中,您也可以使用ctypes GetSystemMetrics()

import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)

这样你就不需要安装pywin32包了; 它不需要Python本身没有的任何东西。

对于多显示器设置,您可以检索虚拟显示器的组合宽度和高度:

import ctypes
user32 = ctypes.windll.user32
screensize = user32.GetSystemMetrics(78), user32.GetSystemMetrics(79)

83
2018-06-28 00:54



它甚至可以在Wine上使用。 - jfs
重要说明:如果使用DPI缩放(例如:通常是4k显示的情况),返回的值可能不正确,您必须在初始化GUI组件之前调用SetProcessDPIAware(而不是在调用GetSystemMetrics函数之前)。对于win32平台上的大多数答案(GTK等)都是如此。 - totaam
对于多个监视器,您可以使用GetSystemMetrics(78)和GetSystemMetrics(79) - Derek
@Derek是什么 GetSystemMetrics(78) 和 GetSystemMetrics(79) 返回? - Steven Vascellaro
@StevenVascellaro虚拟屏幕的宽度/高度,以像素为单位。 msdn.microsoft.com/en-us/library/windows/desktop/... - Derek


我创造了一个 PyPI模块 出于这样的原因:

pip install screeninfo

代码:

from screeninfo import get_monitors
for m in get_monitors():
    print(str(m))

结果:

monitor(1920x1080+1920+0)
monitor(1920x1080+0+0)

它支持多监视器环境。它的目标是跨平台;现在它支持Cygwin和X11,但拉取请求是完全受欢迎的。


45
2017-07-01 20:50



在Windows上工作得很好但Mac我得到以下错误:ImportError:无法加载X11 - Chris Lucian
在Ubuntu上运行得很好。在Ubuntu 16.04上测试过。 - Dhruv Reshamwala
仅供参考,Windows DPI缩放仍然适用。这一行告诉Windows你想要原始的,未缩放的分辨率:“import ctypes; user32 = ctypes.windll.user32; user32.SetProcessDPIAware()”。 1)你的答案应该是最重要的;做得好。 2)我的评论是特定于Windows的,而不是特定于库的(即screeninfo)3)代码从KobeJohn的评论中获取和测试: stackoverflow.com/a/32541666/2616321 - Jason2616321


如果你正在使用wxWindows,你可以简单地做:

import wx

app = wx.App(False) # the wx.App object must be created first.    
print(wx.GetDisplaySize())  # returns a tuple

39
2018-06-28 00:42



+1用于跨平台答案。 - Xavier Ho
这是最好的......谁没有wx? :)加上几行而不是你眼睛上的一堆代码。这是我的默认方法,谢谢。 - erm3nda
这应该是 app = wx.App(False) 否则你得到“必须首先创建wx.App对象。”错误。 26票,没人检查?在没有将wx实例赋予变量的情况下在Windows中工作吗? - erm3nda
谁没有wx?很多人? - marsh


直接来自这篇文章的答案: 如何获得Tkinter的屏幕尺寸?

import tkinter as tk

root = tk.Tk()

screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

25
2018-05-13 19:29



如果将外部显示扩展到主显示屏旁边,则此方法将提供所有显示分辨率的总和,而不是当前显示分辨​​率。 - jadelord


在Windows 8.1上,我无法从ctypes或tk获得正确的解决方案。 其他人对ctypes也有同样的问题: getsystemmetrics返回错误的屏幕大小 要在Windows 8.1上获得高DPI监视器的正确完整分辨率,必须调用SetProcessDPIAware并使用以下代码:

import ctypes
user32 = ctypes.windll.user32
user32.SetProcessDPIAware()
[w, h] = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]

详细信息如下:

我发现这是因为Windows报告的是缩放分辨率。看来python默认是'system dpi aware'应用程序。此处列出了DPI感知应用程序的类型: http://msdn.microsoft.com/en-us/library/windows/desktop/dn469266%28v=vs.85%29.aspx#dpi_and_the_desktop_scaling_factor

基本上,不是显示内容的完整显示器分辨率,这将使字体变得微小,而是将内容放大,直到字体足够大。

在我的显示器上,我得到:
物理分辨率:2560 x 1440(220 DPI)
报告的python分辨率:1555 x 875(158 DPI)

根据这个windows网站: http://msdn.microsoft.com/en-us/library/aa770067%28v=vs.85%29.aspx 报告的系统有效分辨率的公式为: (reported_px * current_dpi)/(96 dpi)= physical_px

我可以使用以下代码获得正确的全屏分辨率和当前DPI。 请注意,我调用SetProcessDPIAware()以允许程序查看真实分辨率。

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))    

返回的是:

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

我正在运行带有220 DPI显示器的Windows 8.1。 我的显示缩放将当前的DPI设置为158。

我将使用158来确保我的matplotlib图是正确的尺寸: 来自pylab import rcParams rcParams ['figure.dpi'] = curr_dpi


17
2017-10-23 23:20



你在这里有很多好的信息,但答案本身就埋藏在中间。为了使它更容易阅读,你能否准确地澄清答案是什么和 然后 提供背景资料? - skrrgwasme
我编辑了我的帖子以在开头显示答案,然后进入细节。感谢您的反馈。 - spacether
看起来这里的计算存在缺陷,很容易发现你从报告的宽度和高度(以英寸为单位)计算出对角线尺寸。据报道,对角线为13.3英寸的屏幕为15英寸。它似乎 Tkinter 使用正确的像素,但不知道dpi缩放因此报告错误的mm尺寸。 - Primer
这在Windows 10上不起作用,SetSystemDPIAware()似乎没有什么区别。但是,调用ctypes.windll.shcore.SetProcessDpiAwareness(2)似乎可以解决问题。 - Klamer Schutte


为了完整起见,Mac OS X.

import AppKit
[(screen.frame().size.width, screen.frame().size.height)
    for screen in AppKit.NSScreen.screens()]

将为您提供包含所有屏幕大小的元组列表(如果存在多个监视器)


14
2018-06-28 01:09





如果你正在使用 Qt 工具包具体 PySide,你可以做到以下几点:

from PySide import QtGui
import sys

app = QtGui.QApplication(sys.argv)
screen_rect = app.desktop().screenGeometry()
width, height = screen_rect.width(), screen_rect.height()

13
2017-07-04 16:42





这是一个快速的小Python程序,它将显示有关多显示器设置的信息:

import gtk

window = gtk.Window()

# the screen contains all monitors
screen = window.get_screen()
print "screen size: %d x %d" % (gtk.gdk.screen_width(),gtk.gdk.screen_height())

# collect data about each monitor
monitors = []
nmons = screen.get_n_monitors()
print "there are %d monitors" % nmons
for m in range(nmons):
  mg = screen.get_monitor_geometry(m)
  print "monitor %d: %d x %d" % (m,mg.width,mg.height)
  monitors.append(mg)

# current monitor
curmon = screen.get_monitor_at_window(screen.get_active_window())
x, y, width, height = monitors[curmon]
print "monitor %d: %d x %d (current)" % (curmon,width,height)  

以下是其输出的示例:

screen size: 5120 x 1200
there are 3 monitors
monitor 0: 1600 x 1200
monitor 1: 1920 x 1200
monitor 2: 1600 x 1200
monitor 1: 1920 x 1200 (current)

12
2018-05-12 11:39



是否 gtk.Window() 得到的 gdk_default_root_window?这是你如何确定的 .get_screen 包含所有显示器? - yatg
我问,因为在我的代码中我试图复制你的代码,我在jsctypes做它,它一直告诉我0监视器: gist.github.com/yajd/55441c9c3d0711ee4a38#file-gistfile1-txt-L3 - yatg
我写这段代码已经有一段时间但是,如果我没记错的话,那是什么 gtk.Window() 确实是创造一个新窗口(见 这里)。窗口只是一种使用方式 get_screen 获取监视器信息。它返回窗口所在的屏幕(或者如果它曾经显示过的话)。我想这取决于X配置是否“屏幕”包含所有“监视器”。它在我的Twinview系统上运行。 - starfry
谢谢@starfry!我需要找到一个交叉解决方案,无论屏幕如何,都能获得所有显示器及其尺寸。你有没有开发类似的东西? :) - yatg


使用Linux,最简单的方法是执行bash命令

xrandr | grep '*'

并使用regexp解析其输出。

你也可以通过PyGame来做到这一点: http://www.daniweb.com/forums/thread54881.html


11
2018-06-27 23:53



你如何使用pygame来获得屏幕分辨率? - Jamie Twells
stackoverflow.com/a/19954583/344347 - Pavel Strakhov


我在我的一个项目中使用get_screen_resolution方法,如下面的一个,它基本上是一个导入链。您可以根据您的需要通过删除不需要的部分来修改它,并在链中向上移动更多可能的端口。

PYTHON_V3 = sys.version_info >= (3,0,0) and sys.version_info < (4,0,0):
#[...]
    def get_screen_resolution(self, measurement="px"):
        """
        Tries to detect the screen resolution from the system.
        @param measurement: The measurement to describe the screen resolution in. Can be either 'px', 'inch' or 'mm'. 
        @return: (screen_width,screen_height) where screen_width and screen_height are int types according to measurement.
        """
        mm_per_inch = 25.4
        px_per_inch =  72.0 #most common
        try: # Platforms supported by GTK3, Fx Linux/BSD
            from gi.repository import Gdk 
            screen = Gdk.Screen.get_default()
            if measurement=="px":
                width = screen.get_width()
                height = screen.get_height()
            elif measurement=="inch":
                width = screen.get_width_mm()/mm_per_inch
                height = screen.get_height_mm()/mm_per_inch
            elif measurement=="mm":
                width = screen.get_width_mm()
                height = screen.get_height_mm()
            else:
                raise NotImplementedError("Handling %s is not implemented." % measurement)
            return (width,height)
        except:
            try: #Probably the most OS independent way
                if PYTHON_V3: 
                    import tkinter 
                else:
                    import Tkinter as tkinter
                root = tkinter.Tk()
                if measurement=="px":
                    width = root.winfo_screenwidth()
                    height = root.winfo_screenheight()
                elif measurement=="inch":
                    width = root.winfo_screenmmwidth()/mm_per_inch
                    height = root.winfo_screenmmheight()/mm_per_inch
                elif measurement=="mm":
                    width = root.winfo_screenmmwidth()
                    height = root.winfo_screenmmheight()
                else:
                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                return (width,height)
            except:
                try: #Windows only
                    from win32api import GetSystemMetrics 
                    width_px = GetSystemMetrics (0)
                    height_px = GetSystemMetrics (1)
                    if measurement=="px":
                        return (width_px,height_px)
                    elif measurement=="inch":
                        return (width_px/px_per_inch,height_px/px_per_inch)
                    elif measurement=="mm":
                        return (width_px/mm_per_inch,height_px/mm_per_inch)
                    else:
                        raise NotImplementedError("Handling %s is not implemented." % measurement)
                except:
                    try: # Windows only
                        import ctypes
                        user32 = ctypes.windll.user32
                        width_px = user32.GetSystemMetrics(0)
                        height_px = user32.GetSystemMetrics(1)
                        if measurement=="px":
                            return (width_px,height_px)
                        elif measurement=="inch":
                            return (width_px/px_per_inch,height_px/px_per_inch)
                        elif measurement=="mm":
                            return (width_px/mm_per_inch,height_px/mm_per_inch)
                        else:
                            raise NotImplementedError("Handling %s is not implemented." % measurement)
                    except:
                        try: # Mac OS X only
                            import AppKit 
                            for screen in AppKit.NSScreen.screens():
                                width_px = screen.frame().size.width
                                height_px = screen.frame().size.height
                                if measurement=="px":
                                    return (width_px,height_px)
                                elif measurement=="inch":
                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                elif measurement=="mm":
                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                else:
                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                        except: 
                            try: # Linux/Unix
                                import Xlib.display
                                resolution = Xlib.display.Display().screen().root.get_geometry()
                                width_px = resolution.width
                                height_px = resolution.height
                                if measurement=="px":
                                    return (width_px,height_px)
                                elif measurement=="inch":
                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                elif measurement=="mm":
                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                else:
                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                            except:
                                try: # Linux/Unix
                                    if not self.is_in_path("xrandr"):
                                        raise ImportError("Cannot read the output of xrandr, if any.")
                                    else:
                                        args = ["xrandr", "-q", "-d", ":0"]
                                        proc = subprocess.Popen(args,stdout=subprocess.PIPE)
                                        for line in iter(proc.stdout.readline,''):
                                            if isinstance(line, bytes):
                                                line = line.decode("utf-8")
                                            if "Screen" in line:
                                                width_px = int(line.split()[7])
                                                height_px = int(line.split()[9][:-1])
                                                if measurement=="px":
                                                    return (width_px,height_px)
                                                elif measurement=="inch":
                                                    return (width_px/px_per_inch,height_px/px_per_inch)
                                                elif measurement=="mm":
                                                    return (width_px/mm_per_inch,height_px/mm_per_inch)
                                                else:
                                                    raise NotImplementedError("Handling %s is not implemented." % measurement)
                                except:
                                    # Failover
                                    screensize = 1366, 768
                                    sys.stderr.write("WARNING: Failed to detect screen size. Falling back to %sx%s" % screensize)
                                    if measurement=="px":
                                        return screensize
                                    elif measurement=="inch":
                                        return (screensize[0]/px_per_inch,screensize[1]/px_per_inch)
                                    elif measurement=="mm":
                                        return (screensize[0]/mm_per_inch,screensize[1]/mm_per_inch)
                                    else:
                                        raise NotImplementedError("Handling %s is not implemented." % measurement)

7
2018-01-19 04:18



感谢分享这个,但通过使用函数来处理if-else案例可能会缩短很多 - Udayraj Deshmukh