2009-12-30 4 views
20

Come posso cambiare lo sfondo del mio desktop con python?Come posso cambiare lo sfondo del mio desktop con python?

Voglio farlo sia in Windows che in Linux.

+2

per il Linux-metà della tua domanda, (e assumendo un ambiente desktop GNOME), si potrebbe voler dare un'occhiata a http://oracle.bridgewayconsulting.com.au/~danni/misc/ change-background-py.html – unutbu

+0

Qualcuno sa come farlo in KDE? – TheInitializer

risposta

10

Su un desktop GNOME, di solito si esegue questa operazione con gconf, sia chiamando direttamente gconftool o utilizzando il modulo gconf pitone. Quest'ultimo è nel link dato da unutbu. Il primo metodo potrebbe essere fatto in questo modo.

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 
+0

Per Ubuntu 11.04 questo non sembra funzionare. L'impostazione gconf cambia, ma lo sfondo non si aggiorna alla nuova immagine. – hobs

+0

Sto usando 11.04 e ho appena scritto uno script che scorre le immagini in una cartella, e ho usato questo frammento. Ha funzionato bene per me. Tuttavia, sto eseguendo il comando con os.system (comando) – MikeVaughan

2

Su Windows, avrete bisogno di qualche trucco con pywin32 e the windows API, su 'linux' la risposta dipenderà da quale desktop è in esecuzione - KDE, Gnome, o qualcosa di più esotico. Sotto KDE (e forse Gnome) puoi probabilmente inviare un messaggio usando D-Bus, che potresti fare senza includere nuove librerie usando lo strumento da riga di comando dbus-send.

L'altra opzione sarebbe quella di impostare lo sfondo del desktop in un file che poi modificare/sostituire in pitone - ma questo probabilmente comporterà solo un cambiamento quando l'utente accede a

32

su Windows con python2.. 5 o versione successiva, utilizzare i tipi di codice per caricare user32.dll e chiamare SystemParametersInfo() con l'azione SPI_SETDESKWALLPAPER.

Ad esempio:

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

+1 ctypes è preferibile a pywin32 – James

+2

Non sembra funzionare con un .jpg, funziona con un .bmp tho (su xp) – Noelkd

+2

Ho usato con successo un jpg su win 7 – CrazyPenguin

6

in GNOME, è probabilmente preferibile utilizzare il pitone legame di gconf direttamente:

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

In primo luogo, l'importazione ctypes: esso consente di accedere ai componenti di Windows, come lo screensaver, sfondi, ecc .

Quindi chiamare ctypes.windll.user32.SystemParametersInfoA(a,b,c,d):

a = 20

b = 0

c = Il percorso completo dell'immagine. Not just the path from the active directory

d = 0

9

Io uso il seguente metodo in uno dei miei primi progetti:

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.") 

Il metodo get_desktop_environment è stata pubblicata in another thread.

+1

Invece della funzione 'get_home_dir()', puoi semplicemente usare 'os.path.expanduser ('~')' –

1

cambiare l'immagine della scrivania

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

sfondo ha funzionato bene per me. windows10, python27

2

C'è una differenza tra il metodo SystemParametersInfo da chiamare in base a ciò che accade se si utilizza il sistema operativo a 64 bit o 32 bit. Per 64 bit è necessario utilizzare SystemParametersInfoW (Unicode) e per il 32 bit 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() 
+1

Questo non ha senso. La scelta di ASCII o Unicode è completamente indipendente dal fatto che si stiano utilizzando Windows a 32 o 64 bit. (Dovevi usare ASCII su Windows a 16 bit e Windows 95/98/ME, ma Windows NT ha sempre supportato Unicode, entrambe le versioni a 32 e 64 bit.) –

+0

@HarryJohnston come spieghi 'SystemParametersInfoA' non funziona su Windows 10 a 64 bit? – Johnny

+1

@Johnny, l'ho appena provato e funziona perfettamente per me. Quello è da C, bada bene, quindi è ancora * possibile * che ci sia qualche stranezza legata a Python che in qualche modo dipende dal buon senso del sistema operativo, anche se sembra molto improbabile. Osservando la documentazione dei ctypes, * dovrebbe * dipendere solo dal fatto che tu stia usando Python 2 o Python 3. –

6

Per Python3.5, SystemParametersInfoA non funziona.Usa SystemParametersInfoW.

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

È Python o i tipi di Windows utilizzati? – Johnny

+0

Python2 utilizza ** SystemParametersInfoA ** e Python3 utilizza ** SystemParametersInfoW ** – mesksr