我正在运行 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())
import Xlib.display
display = Xlib.display.Display()
root = display.screen().root
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 将多个显示器加入到虚拟显示器中......
- X11 显示器是指整个 X 服务器
- 同一主机上的不同 X11 显示器→可能是不同的用户
- 用户拥有的所有键盘和鼠标(通常每个键盘和鼠标之一(都属于一个 X11 显示器
- 如今,每个 X11 显示器一个 X11 屏幕
- 每个 X11 显示器有多个 X11 屏幕实际上指的是一个已经消亡的概念。
- 想象一下,鼠标和键盘完全由其他方式共享不同的输出设备
- 无法在 X11 屏幕之间共享或移动窗口
- 可以为每个 X11 屏幕运行不同的窗口管理器
- 或者至少必须运行完全独立的窗口管理器实例
- 没有证明很有用
- 今天的 X11 屏幕必须包含所有显示器
- 通常是一个大矩形将它们全部包围起来
- 有一个来自 (X11( EWMH 规范的桌面术语
- 如果将 X11 屏幕视为一个桌面,则由窗口管理器决定
- 。或者如果它将每个显示器视为桌面
- 想要在 (X11 EWMH( 桌面之间移动其窗口的 X11 应用程序("客户端"(可能需要为不同的窗口管理器执行不同的操作
- 但应用程序大多将其留给窗口管理器和用户,以全屏或通过(X11 EWMH(桌面或显示器组织它们 。
你只需要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()))