Изменение разрешения экрана с помощью python с кросс-платформенной поддержкой


Изменение разрешения экрана с помощью функции 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 12

3 ответа:

Ниже представлено решение, которое работает на 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

Многие ответы уже разбросаны по StackOverflow и могут быть обобщены следующим образом.

, чтобы получить разрешение на 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()]

По-видимому, понимание списка будет повторяться экраны в установке нескольких мониторов.

Я думаю, что ответ Алекса Мартелли на соответствующий вопрос (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 для установки разрешения (docs: http://www.pygame.org/docs/ref/display.html#pygame.display.set_mode ). Вот фрагмент документов для set_mode:

"аргумент разрешения представляет собой пару чисел, представляющих ширину и высоту. Аргумент flags представляет собой набор дополнительных параметров. Аргумент depth представляет собой количество битов, используемых для цвета."

Может быть, это поможет вам начать. По крайней мере, вы могли бы, возможно, проверить исходный код для set_mode, чтобы увидеть, если есть некоторые возможные вдохновение есть, если вы не можете использовать его непосредственно.

Другие потенциально полезные идеи:

  1. вы можете сделать грубую проверку платформы с помощью sys.platform (docs: http://docs.python.org/2/library/sys.html#sys.platform ). Это возвращает 'darwin' на MacOS.
  2. битовая архитектура должна быть доступна с модулем Python platform. Если я запускаю platform.architecture() на моей машине, он возвращает кортеж: ('64bit', '') (docs: http://docs.python.org/2/library/platform.html#platform.architecture )

Чтобы получить и установить разрешение под Windows (как 32, так и 64 бита), вы можете использовать ctypes и user32 dll (ctypes.уиндл.user32). Не заботьтесь о "32" в названии dll-это 64-битная dll на 64-битной Windows. Эту библиотеку можно также использовать для поиска разрешенных разрешений.

В качестве альтернативы вы можете использовать некоторые инструменты командной строки, такие как nircmd.exe :

nircmd.exe 1024 768 32

Последнее число-это глубина цвета.

Надеюсь, это поможет.