Подтвердить что ты не робот

Как изменить фон рабочего стола на python?

Как изменить фон рабочего стола на python?

Я хочу сделать это как в Windows, так и в Linux.

4b9b3361

Ответ 1

В Windows с python2.5 или выше используйте ctypes для загрузки user32.dll и вызывайте SystemParametersInfo() с действием SPI_SETDESKWALLPAPER.

Например:

import ctypes
SPI_SETDESKWALLPAPER = 20 
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, "image.jpg" , 0)

Ответ 2

Для Python3.5 SystemParametersInfoA не работает. Использовать SystemParametersInfoW.

import ctypes
ctypes.windll.user32.SystemParametersInfoW(20, 0, "absolute path" , 0)

Ответ 3

На рабочем столе gnome вы обычно делаете это с помощью gconf, либо напрямую вызываете gconftool, либо используя модуль gconf python. Последний находится в ссылке, данной unutbu. Первый способ можно сделать следующим образом.

import commands
command = "gconftool-2 --set /desktop/gnome/background/picture_filename --type string '/path/to/file.jpg'"
status, output = commands.getstatusoutput(command)  # status=0 if success

Ответ 4

Я использую следующий метод в одном из моих первоначальных проектов:

    def set_wallpaper(self,file_loc, first_run):
        # Note: There are two common Linux desktop environments where 
        # I have not been able to set the desktop background from 
        # command line: KDE, Enlightenment
        desktop_env = self.get_desktop_environment()
        try:
            if desktop_env in ["gnome", "unity", "cinnamon"]:
                uri = "'file://%s'" % file_loc
                try:
                    SCHEMA = "org.gnome.desktop.background"
                    KEY = "picture-uri"
                    gsettings = Gio.Settings.new(SCHEMA)
                    gsettings.set_string(KEY, uri)
                except:
                    args = ["gsettings", "set", "org.gnome.desktop.background", "picture-uri", uri]
                    subprocess.Popen(args)
            elif desktop_env=="mate":
                try: # MATE >= 1.6
                    # info from http://wiki.mate-desktop.org/docs:gsettings
                    args = ["gsettings", "set", "org.mate.background", "picture-filename", "'%s'" % file_loc]
                    subprocess.Popen(args)
                except: # MATE < 1.6
                    # From https://bugs.launchpad.net/variety/+bug/1033918
                    args = ["mateconftool-2","-t","string","--set","/desktop/mate/background/picture_filename",'"%s"' %file_loc]
                    subprocess.Popen(args)
            elif desktop_env=="gnome2": # Not tested
                # From https://bugs.launchpad.net/variety/+bug/1033918
                args = ["gconftool-2","-t","string","--set","/desktop/gnome/background/picture_filename", '"%s"' %file_loc]
                subprocess.Popen(args)
            ## KDE4 is difficult
            ## see http://blog.zx2c4.com/699 for a solution that might work
            elif desktop_env in ["kde3", "trinity"]:
                # From http://ubuntuforums.org/archive/index.php/t-803417.html
                args = 'dcop kdesktop KBackgroundIface setWallpaper 0 "%s" 6' % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="xfce4":
                #From http://www.commandlinefu.com/commands/view/2055/change-wallpaper-for-xfce4-4.6.0
                if first_run:
                    args0 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-path", "-s", file_loc]
                    args1 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-style", "-s", "3"]
                    args2 = ["xfconf-query", "-c", "xfce4-desktop", "-p", "/backdrop/screen0/monitor0/image-show", "-s", "true"]
                    subprocess.Popen(args0)
                    subprocess.Popen(args1)
                    subprocess.Popen(args2)
                args = ["xfdesktop","--reload"]
                subprocess.Popen(args)
            elif desktop_env=="razor-qt": #TODO: implement reload of desktop when possible
                if first_run:
                    desktop_conf = configparser.ConfigParser()
                    # Development version
                    desktop_conf_file = os.path.join(self.get_config_dir("razor"),"desktop.conf") 
                    if os.path.isfile(desktop_conf_file):
                        config_option = r"screens\1\desktops\1\wallpaper"
                    else:
                        desktop_conf_file = os.path.join(self.get_home_dir(),".razor/desktop.conf")
                        config_option = r"desktops\1\wallpaper"
                    desktop_conf.read(os.path.join(desktop_conf_file))
                    try:
                        if desktop_conf.has_option("razor",config_option): #only replacing a value
                            desktop_conf.set("razor",config_option,file_loc)
                            with codecs.open(desktop_conf_file, "w", encoding="utf-8", errors="replace") as f:
                                desktop_conf.write(f)
                    except:
                        pass
                else:
                    #TODO: reload desktop when possible
                    pass 
            elif desktop_env in ["fluxbox","jwm","openbox","afterstep"]:
                #http://fluxbox-wiki.org/index.php/Howto_set_the_background
                # used fbsetbg on jwm too since I am too lazy to edit the XML configuration 
                # now where fbsetbg does the job excellent anyway. 
                # and I have not figured out how else it can be set on Openbox and AfterSTep
                # but fbsetbg works excellent here too.
                try:
                    args = ["fbsetbg", file_loc]
                    subprocess.Popen(args)
                except:
                    sys.stderr.write("ERROR: Failed to set wallpaper with fbsetbg!\n")
                    sys.stderr.write("Please make sre that You have fbsetbg installed.\n")
            elif desktop_env=="icewm":
                # command found at http://urukrama.wordpress.com/2007/12/05/desktop-backgrounds-in-window-managers/
                args = ["icewmbg", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="blackbox":
                # command found at http://blackboxwm.sourceforge.net/BlackboxDocumentation/BlackboxBackground
                args = ["bsetbg", "-full", file_loc]
                subprocess.Popen(args)
            elif desktop_env=="lxde":
                args = "pcmanfm --set-wallpaper %s --wallpaper-mode=scaled" % file_loc
                subprocess.Popen(args,shell=True)
            elif desktop_env=="windowmaker":
                # From http://www.commandlinefu.com/commands/view/3857/set-wallpaper-on-windowmaker-in-one-line
                args = "wmsetbg -s -u %s" % file_loc
                subprocess.Popen(args,shell=True)
            ## NOT TESTED BELOW - don't want to mess things up ##
            #elif desktop_env=="enlightenment": # I have not been able to make it work on e17. On e16 it would have been something in this direction
            #    args = "enlightenment_remote -desktop-bg-add 0 0 0 0 %s" % file_loc
            #    subprocess.Popen(args,shell=True)
            #elif desktop_env=="windows": #Not tested since I do not run this on Windows
            #    #From https://stackoverflow.com/questions/1977694/change-desktop-background
            #    import ctypes
            #    SPI_SETDESKWALLPAPER = 20
            #    ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, file_loc , 0)
            #elif desktop_env=="mac": #Not tested since I do not have a mac
            #    #From https://stackoverflow.com/questions/431205/how-can-i-programatically-change-the-background-in-mac-os-x
            #    try:
            #        from appscript import app, mactypes
            #        app('Finder').desktop_picture.set(mactypes.File(file_loc))
            #    except ImportError:
            #        #import subprocess
            #        SCRIPT = """/usr/bin/osascript<<END
            #        tell application "Finder" to
            #        set desktop picture to POSIX file "%s"
            #        end tell
            #        END"""
            #        subprocess.Popen(SCRIPT%file_loc, shell=True)
            else:
                if first_run: #don't spam the user with the same message over and over again
                    sys.stderr.write("Warning: Failed to set wallpaper. Your desktop environment is not supported.")
                    sys.stderr.write("You can try manually to set Your wallpaper to %s" % file_loc)
                return False
            return True
        except:
            sys.stderr.write("ERROR: Failed to set wallpaper. There might be a bug.\n")
            return False

    def get_config_dir(self, app_name=APP_NAME):
        if "XDG_CONFIG_HOME" in os.environ:
            confighome = os.environ['XDG_CONFIG_HOME'] 
        elif "APPDATA" in os.environ: # On Windows
            confighome = os.environ['APPDATA'] 
        else:
            try:
                from xdg import BaseDirectory   
                confighome =  BaseDirectory.xdg_config_home
            except ImportError: # Most likely a Linux/Unix system anyway
                confighome =  os.path.join(self.get_home_dir(),".config")
        configdir = os.path.join(confighome,app_name)
        return configdir

    def get_home_dir(self):
        if sys.platform == "cygwin":
            home_dir = os.getenv('HOME')
        else:
            home_dir = os.getenv('USERPROFILE') or os.getenv('HOME')
        if home_dir is not None:
            return os.path.normpath(home_dir)
        else:
            raise KeyError("Neither USERPROFILE or HOME environment variables set.")

Метод get_desktop_environment опубликован в другом потоке.

Ответ 5

В gnome, вероятно, предпочтительнее использовать прямое связывание gconf с python:

import gconf
conf = gconf.client_get_default()
conf.set_string('/desktop/gnome/background/picture_filename','/path/to/filename.jpg')

Ответ 6

В окнах вам понадобятся некоторые трюки с pywin32 и API Windows, на 'linux' ответ будет зависеть от того, какой рабочий стол запущен - KDE, Gnome или что-то более экзотическое. В KDE (и, возможно, Gnome) вы, вероятно, можете отправить сообщение с помощью D-Bus, которое вы могли бы сделать без включения каких-либо новых библиотек с помощью инструмента командной строки dbus-send.

Другой вариант - установить обои рабочего стола в файл, который вы затем отредактируете/замените на python, но это, вероятно, приведет только к изменению при входе пользователя в систему.

Ответ 7

Во-первых, import ctypes: он дает вам доступ к компонентам Windows, таким как заставка, обои и т.д.

Затем вызовите ctypes.windll.user32.SystemParametersInfoA(a,b,c,d):

a= 20

b= 0

c= Путь COMPLETE изображения. Не только путь из активного каталога

d= 0

Ответ 8

изменение фонового изображения рабочего стола

    import ctypes
    import os
    SPI_SETDESKWALLPAPER = 20 
    ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, 'your image path', 3) 
    #'C:\\Users\\Public\\Pictures\\abc.jpg'

это сработало для меня. windows10, python27

Ответ 9

Есть разница в том, какой метод SystemParametersInfo вызывается на основе того, что если вы работаете на 64-битной или 32-разрядной ОС. Для 64 бит вы должны использовать SystemParametersInfoW (Unicode) и для 32-битного SystemParametersInfoA (ANSI)

import struct
import ctypes


SPI_SETDESKWALLPAPER = 20
WALLPAPER_PATH = 'C:\\your_file_name.jpg'


def is_64_windows():
    """Find out how many bits is OS. """
    return struct.calcsize('P') * 8 == 64


def get_sys_parameters_info():
    """Based on if this is 32bit or 64bit returns correct version of SystemParametersInfo function. """
    return ctypes.windll.user32.SystemParametersInfoW if is_64_windows() \
        else ctypes.windll.user32.SystemParametersInfoA


def change_wallpaper():
    sys_parameters_info = get_sys_parameters_info()
    r = sys_parameters_info(SPI_SETDESKWALLPAPER, 0, WALLPAPER_PATH, 3)

    # When the SPI_SETDESKWALLPAPER flag is used,
    # SystemParametersInfo returns TRUE
    # unless there is an error (like when the specified file doesn't exist).
    if not r:
        print(ctypes.WinError())


change_wallpaper()

Ответ 10

import ctypes,win32con

def getWallpaper():
    ubuf = ctypes.create_unicode_buffer(512)
    ctypes.windll.user32.SystemParametersInfoW(win32con.SPI_GETDESKWALLPAPER,len(ubuf),ubuf,0)
    return ubuf.value

def setWallpaper(path):
    changed = win32con.SPIF_UPDATEINIFILE | win32con.SPIF_SENDCHANGE
    ctypes.windll.user32.SystemParametersInfoW(win32con.SPI_SETDESKWALLPAPER,0,path,changed)

В качестве альтернативы: (с SystemParametersInfoA)

def getWallpaper():
    sbuf = ctypes.create_string_buffer(512) # ctypes.c_buffer(512)
    ctypes.windll.user32.SystemParametersInfoA(win32con.SPI_GETDESKWALLPAPER,len(sbuf),sbuf,0)
    return sbuf.value

def setWallpaper(path):
    changed = win32con.SPIF_UPDATEINIFILE | win32con.SPIF_SENDCHANGE
    ctypes.windll.user32.SystemParametersInfoA(win32con.SPI_SETDESKWALLPAPER,0,path.encode(),changed) # "".encode() = b""

Аргументы:
SystemParametersInfo(SetOrGet, GetBufferSize, SetBufferOrGetBuffer, SetChange)

Путь должен быть абсолютным, поэтому, если вы используете что-то относительно вашего скрипта, выполните:
path = os.path.abspath(path)

Чтобы увидеть больше вещей, которые вы можете сделать с SystemParametersInfo, смотрите документацию.
(внизу есть пример изменения скорости мыши)

PS Здесь уже есть много ответов, но они пропускают вещание, которое вы должны делать. Конечно, это работает без него, но это плохая практика, чтобы не использовать его должным образом.

PPS И они дали только жестко закодированные значения, а не переменные, из которых они происходят.

Также обратите внимание, я использую 512 символов для размера буфера при получении пути, просто чтобы быть более безопасным, так как пути могут превышать 256. Я сомневаюсь, что у кого-нибудь будут пути до тех пор, как этот.

Еще одна заметка. Я только протестировал приведенные выше примеры в Python 3, но я не думаю, что SystemParametersInfoA нуждается в .encode() в Python 2. (они обновили строки в Python 3 для Unicode, я полагаю) Строка в SystemParametersInfoW может потребоваться преобразование для Python 2.