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

Изменить разрешение экрана с помощью функции python. Это должна быть кросс-платформа, то есть поддержка окон, linux и mac (все в порядке, чтобы иметь несколько случаев в зависимости от операционной системы)

У меня есть код, который, я думаю, работает на linux (Ubuntu) Я ищу решение для windows и mac (должно поддерживать как 32, так и 64-разрядные машины)

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

Я также был бы признателен, если бы кто-нибудь мог сказать мне, как я могу получить возможные разрешения экрана для окон и 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

Ответ 1

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

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

Чтобы получить разрешение на Windows в чисто питоническом стиле (ссылка: fooobar.com/questions/92345/...):

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

Решение MacOS также использует Python, но использует пакет за пределами стандартной библиотеки (ссылка: fooobar.com/questions/92345/...):

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

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

Я думаю, что ответ Alex Martelli на соответствующий вопрос (fooobar.com/questions/492096/...) также примечателен. Он использует:

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, чтобы увидеть, есть ли там какое-то возможное вдохновение, если вы не можете использовать его напрямую.

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

Ответ 3

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

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

nircmd.exe 1024 768 32

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

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