使用跨平台支持的python调整显示分辨率

时间:2013-12-30 11:03:21

标签: python windows cross-platform desktop-application screen-resolution

使用python函数调整显示分辨率。它应该是跨平台的,即支持windows,linux和mac(根据操作系统可以有多个案例)

我有代码,我认为在linux上工作(Ubuntu)我正在寻找一个Windows和Mac的解决方案(应该支持32位和64位机器)

def SetResolution(width, height):
    os.popen("xrandr -s "+str(width)+'x'+str(height))

如果有人能告诉我如何为windows和mac获取可能的显示分辨率,我也会感激

我在linux上的功能就是:

def GetResolutions():
    screen = os.popen("xrandr").readlines()
    possibleResolutions = []
    for a in screen:
        data = a.split()
        if len(data)<4:
            width, height = data[0].split('x')
            fps = re.sub("[^0-9.]", "", data[1])
            possibleResolutions.append({'width':int(width),'height':int(height),'fps':float(fps)})
            if '*' in data[1]:
                currentResolution = {'width':int(width),'height':int(height),'fps':float(fps)}
    return possibleResolutions, currentResolution

3 个答案:

答案 0 :(得分:7)

许多答案已经散布在StackOverflow周围,可归纳如下。

以纯粹的pythonic方式在Windows上获得分辨率(参考:https://stackoverflow.com/a/3129524/2942522):

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

MacOS解决方案也使用Python,但使用标准库之外的包(参考:https://stackoverflow.com/a/3129567/2942522):

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

显然,列表理解将在多显示器设置中迭代屏幕。

我认为Alex Martelli对相关问题(https://stackoverflow.com/a/2662892/2942522)的回应也值得注意。他使用:

pygame.display.list_modes()
[(1920, 1080), (1768, 992), (1680, 1050), (1600, 1200), (1600, 1024), (1600, 900
), (1440, 900), (1400, 1050), (1360, 768), (1280, 1024), (1280, 960), (1280, 800
), (1280, 768), (1280, 720), (1152, 864), (1024, 768), (800, 600), (720, 576), (
720, 480), (640, 480)]

获取可用的最大到最小分辨率的列表(尽管pygame如果你走这条路线会成为依赖关系)。相反,我怀疑它在跨平台设置中可以正常工作。此外,他提到了pygame.display.set_mode来设置解决方案(文档:http://www.pygame.org/docs/ref/display.html#pygame.display.set_mode)。以下是set_mode的文档片段:

“resolution参数是一对表示宽度和高度的数字.flags参数是其他选项的集合.strins参数表示用于颜色的位数。”

也许这会让你开始。至少你可以查看set_mode的源代码,看看是否有一些可能的灵感,如果你不能直接使用它。

其他可能有用的想法:

  1. 您可以使用sys.platform(文档:http://docs.python.org/2/library/sys.html#sys.platform)进行原始平台检查。这将在MacOS上返回'darwin'
  2. 可以使用Python platform模块访问位体系结构。如果我在我的计算机上运行platform.architecture(),则会返回一个元组:('64bit', '')(文档:http://docs.python.org/2/library/platform.html#platform.architecture

答案 1 :(得分:7)

以下是适用于Windows的解决方案(取决于pywin32)。有些占位符可以放入现有的linux代码,但我不知道该如何处理OS X.

from __future__ import print_function
import sys

class ScreenRes(object):
    @classmethod
    def set(cls, width=None, height=None, depth=32):
        '''
        Set the primary display to the specified mode
        '''
        if width and height:
            print('Setting resolution to {}x{}'.format(width, height, depth))
        else:
            print('Setting resolution to defaults')

        if sys.platform == 'win32':
            cls._win32_set(width, height, depth)
        elif sys.platform.startswith('linux'):
            cls._linux_set(width, height, depth)
        elif sys.platform.startswith('darwin'):
            cls._osx_set(width, height, depth)

    @classmethod
    def get(cls):
        if sys.platform == 'win32':
            return cls._win32_get()
        elif sys.platform.startswith('linux'):
            return cls._linux_get()
        elif sys.platform.startswith('darwin'):
            return cls._osx_get()

    @classmethod
    def get_modes(cls):
        if sys.platform == 'win32':
            return cls._win32_get_modes()
        elif sys.platform.startswith('linux'):
            return cls._linux_get_modes()
        elif sys.platform.startswith('darwin'):
            return cls._osx_get_modes()

    @staticmethod
    def _win32_get_modes():
        '''
        Get the primary windows display width and height
        '''
        import win32api
        from pywintypes import DEVMODEType, error
        modes = []
        i = 0
        try:
            while True:
                mode = win32api.EnumDisplaySettings(None, i)
                modes.append((
                    int(mode.PelsWidth),
                    int(mode.PelsHeight),
                    int(mode.BitsPerPel),
                    ))
                i += 1
        except error:
            pass

        return modes

    @staticmethod
    def _win32_get():
        '''
        Get the primary windows display width and height
        '''
        import ctypes
        user32 = ctypes.windll.user32
        screensize = (
            user32.GetSystemMetrics(0), 
            user32.GetSystemMetrics(1),
            )
        return screensize

    @staticmethod
    def _win32_set(width=None, height=None, depth=32):
        '''
        Set the primary windows display to the specified mode
        '''
        # Gave up on ctypes, the struct is really complicated
        #user32.ChangeDisplaySettingsW(None, 0)
        import win32api
        from pywintypes import DEVMODEType
        if width and height:

            if not depth:
                depth = 32

            mode = win32api.EnumDisplaySettings()
            mode.PelsWidth = width
            mode.PelsHeight = height
            mode.BitsPerPel = depth

            win32api.ChangeDisplaySettings(mode, 0)
        else:
            win32api.ChangeDisplaySettings(None, 0)


    @staticmethod
    def _win32_set_default():
        '''
        Reset the primary windows display to the default mode
        '''
        # Interesting since it doesn't depend on pywin32
        import ctypes
        user32 = ctypes.windll.user32
        # set screen size
        user32.ChangeDisplaySettingsW(None, 0)

    @staticmethod
    def _linux_set(width=None, height=None, depth=32):
        raise NotImplementedError()

    @staticmethod
    def _linux_get():
        raise NotImplementedError()

    @staticmethod
    def _linux_get_modes():
        raise NotImplementedError()

    @staticmethod
    def _osx_set(width=None, height=None, depth=32):
        raise NotImplementedError()

    @staticmethod
    def _osx_get():
        raise NotImplementedError()

    @staticmethod
    def _osx_get_modes():
        raise NotImplementedError()


if __name__ == '__main__':
    print('Primary screen resolution: {}x{}'.format(
        *ScreenRes.get()
        ))
    print(ScreenRes.get_modes())
    #ScreenRes.set(1920, 1080)
    #ScreenRes.set() # Set defaults

答案 2 :(得分:1)

要在Windows(32位和64位)下获取和设置分辨率,您可以使用ctypes和user32 dll(ctypes.windll.user32)。不关心dll名称中的'32' - 它是64位Windows上的64位dll。您也可以使用此库来发现允许的分辨率。

或者,您可以使用某些命令行工具,例如nircmd.exe

nircmd.exe 1024 768 32

最后一个数字是颜色深度。

希望这有帮助。