我正在运行 Ubuntu,我想获取连接的显示器的数量、它们当前的分辨率以及它们相对于彼此的位置(如果可能)。 因为我不喜欢解析 xrandr 命令行工具的控制台输出(至少在不需要的情况下不会),所以我想使用 Python-XLib 或类似的 Pythonic 方法来做到这一点。
这是我的显示配置的 xrandr 输出:
$ xrandr
Screen 0: minimum 320 x 200, current 2960 x 1050, maximum 8192 x 8192
DVI-0 connected 1680x1050+0+0 (normal left inverted right x axis y axis) 473mm x 296mm
1680x1050 60.0*+
[some lines cut]
VGA-0 connected 1280x1024+1680+26 (normal left inverted right x axis y axis) 376mm x 301mm
1280x1024 60.0 + 75.0*
[some more lines cut]
我想用Python获取这些值,就像这样:
monitors = get_monitors()
print monitors[0].width # out: 1680
print monitors[1].width # out: 1280
print monitors[0].x_position # out: 0
print monitors[1].x_position # out: 1680
当尝试通过 Python-XLib(或其他库,如 pyGTK 和 pygame)获取信息时,似乎所有监视器都始终作为一个显示器进行处理。例如,这是我迄今为止使用 XLib 得到的:
import Xlib
import Xlib.display
display = Xlib.display.Display(':0')
print display.screen_count() # output: 1
root = display.screen().root
print root.get_geometry().width # output: 2960 -> no way to get width of single monitor?
print root.get_geometry().height # output: 1050
但正如我所说,我更喜欢一种更干净的方法,而无需解析控制台输出。 难道真的没有办法在不解析 xrandr 输出的情况下使用 Python 获取(详细)显示信息吗?
xrandr
只是一个从命令行访问“RandR”X11扩展的客户端。您可以直接从 Python-Xlib 访问该功能。 这里是一个示例(来自Python-Xlib自己的代码!)。
以防万一 URL 再次更改,这里有一小段代码可以帮助我们获取显示模式。我们需要创建窗口(大小等无关紧要):
from __future__ import print_function
from Xlib import X, display
from Xlib.ext import randr
d = display.Display()
s = d.screen()
window = s.root.create_window(0, 0, 1, 1, 1, s.root_depth)
然后我们就可以使用它来查询屏幕资源了。例如,按照OP的例子:
res = randr.get_screen_resources(window)
for mode in res.modes:
w, h = mode.width, mode.height
print("Width: {}, height: {}".format(w, h))
在我的电脑中我得到:
$ python minimal.py
Xlib.protocol.request.QueryExtension
Width: 1600, height: 900
Width: 1440, height: 900
Width: 1360, height: 768
Width: 1360, height: 768
Width: 1152, height: 864
Width: 1024, height: 768
Width: 800, height: 600
Width: 800, height: 600
Width: 640, height: 480
最新片段。它从所有连接的显示器中提取具有当前分辨率的所有模式。
from Xlib import display
from Xlib.ext import randr
def find_mode(id, modes):
for mode in modes:
if id == mode.id:
return "{}x{}".format(mode.width, mode.height)
def get_display_info():
d = display.Display(':0')
screen_count = d.screen_count()
default_screen = d.get_default_screen()
result = []
screen = 0
info = d.screen(screen)
window = info.root
res = randr.get_screen_resources(window)
for output in res.outputs:
params = d.xrandr_get_output_info(output, res.config_timestamp)
if not params.crtc:
continue
crtc = d.xrandr_get_crtc_info(params.crtc, res.config_timestamp)
modes = set()
for mode in params.modes:
modes.add(find_mode(mode, res.modes))
result.append({
'name': params.name,
'resolution': "{}x{}".format(crtc.width, crtc.height),
'available_resolutions': list(modes)
})
return result
print(get_display_info())
您的代码正在获取有关 X11 屏幕的信息。您正在寻找真实+虚拟 (X11) 显示器。所以试试这个:
import Xlib.display
# grab default X11 display (from $DISPLAY environment var)
display = Xlib.display.Display()
# get first and almost always the only X11 screen of this X11 display
screen = display.screen()
# the root window of this screen provides the info we need
root = screen.root
# iterate over the X11 monitors; often equal real monitors
# will include virtual X11 monitors
for m in root.xrandr_get_monitors().monitors:
connector = display.get_atom_name(m.name)
print(f'{connector}, {m.width_in_pixels}x{m.height_in_pixels}, '\
f'x={m.x}, y={m.y}')
给我退货:
HDMI-0, 1920x1080, x=0, y=1050
DVI-0, 1680x1050, x=1920, y=1050
DVI-1, 1680x1050, x=0, y=0
请注意,“显示”和“屏幕”是 X11 技术术语,与现实世界的使用无关。 “监视器”通常是指真实的东西 - 不过,在 X11 中,您可以使用 Xrandr 将多个监视器连接到虚拟监视器中......
您只需要pip3安装Xlib并使用此代码来获取信息:
from Xlib import display
d = display.Display()
screen_count = d.screen_count()
default_screen = d.get_default_screen()
for screen in range(0,screen_count):
info = d.screen(screen)
print("Screen: %s. Default: %s" % (screen, screen==default_screen))
print("Width: %s, height: %s" % (info.width_in_pixels,info.height_in_pixels))
您可以在此处找到从那里获得的属性列表: http://python-xlib.sourceforge.net/doc/html/python-xlib_16.html#SEC15
使用python Xlib库而不是调用命令行。他们都做同样的事情。
要获取窗口中的显示计数,您可以使用
import win32api
print(len(win32api.EnumDisplayMonitors()))