在没有xrandr命令行工具的情况下在Python中获取监视器计数和分辨率



我正在运行 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()))

相关内容

  • 没有找到相关文章

最新更新