使用Python實(shí)現(xiàn)一個(gè)遠(yuǎn)程壁紙?jiān)O(shè)置系統(tǒng)
系統(tǒng)概述
該系統(tǒng)由兩部分組成:
- 發(fā)送端:帶有GUI界面的客戶(hù)端,可選擇圖片并發(fā)送到目標(biāo)計(jì)算機(jī)
- 接收端:后臺(tái)運(yùn)行的服務(wù)端,接收?qǐng)D片并自動(dòng)設(shè)置為桌面壁紙
完整代碼實(shí)現(xiàn)
1. 發(fā)送端代碼
import os
import socket
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image, ImageTk
import json
class RemoteWallpaperClient:
def __init__(self, root):
self.root = root
self.root.title("遠(yuǎn)程壁紙?jiān)O(shè)置客戶(hù)端")
self.root.geometry("500x450")
self.root.resizable(False, False)
# 默認(rèn)服務(wù)器端口
self.default_port = 12345
# 當(dāng)前選擇的圖片路徑
self.current_image_path = None
# 創(chuàng)建界面
self.create_widgets()
def create_widgets(self):
# 主框架
main_frame = ttk.Frame(self.root, padding="20")
main_frame.pack(fill=tk.BOTH, expand=True)
# 標(biāo)題
title_label = ttk.Label(main_frame, text="遠(yuǎn)程壁紙?jiān)O(shè)置客戶(hù)端",
font=("Arial", 16, "bold"))
title_label.pack(pady=10)
# 目標(biāo)計(jì)算機(jī)設(shè)置區(qū)域
target_frame = ttk.LabelFrame(main_frame, text="目標(biāo)計(jì)算機(jī)設(shè)置", padding="10")
target_frame.pack(fill=tk.X, pady=10)
# IP地址輸入
ip_frame = ttk.Frame(target_frame)
ip_frame.pack(fill=tk.X, pady=5)
ttk.Label(ip_frame, text="目標(biāo)IP地址:").pack(side=tk.LEFT)
self.ip_entry = ttk.Entry(ip_frame, width=15)
self.ip_entry.pack(side=tk.LEFT, padx=5)
self.ip_entry.insert(0, "192.168.1.")
# 端口輸入
port_frame = ttk.Frame(target_frame)
port_frame.pack(fill=tk.X, pady=5)
ttk.Label(port_frame, text="端口:").pack(side=tk.LEFT)
self.port_entry = ttk.Entry(port_frame, width=10)
self.port_entry.pack(side=tk.LEFT, padx=5)
self.port_entry.insert(0, str(self.default_port))
# 壁紙選擇區(qū)域
wallpaper_frame = ttk.LabelFrame(main_frame, text="壁紙?jiān)O(shè)置", padding="10")
wallpaper_frame.pack(fill=tk.X, pady=10)
# 選擇壁紙按鈕
select_btn = ttk.Button(wallpaper_frame, text="選擇壁紙圖片",
command=self.select_wallpaper)
select_btn.pack(pady=5)
# 壁紙預(yù)覽區(qū)域
preview_frame = ttk.Frame(wallpaper_frame)
preview_frame.pack(fill=tk.X, pady=5)
self.preview_label = tk.Label(preview_frame, text="未選擇圖片",
relief=tk.SUNKEN, bg='white',
width=50, height=12)
self.preview_label.pack(fill=tk.BOTH, expand=True)
# 按鈕框架
btn_frame = ttk.Frame(main_frame)
btn_frame.pack(pady=10)
# 發(fā)送壁紙按鈕
send_btn = ttk.Button(btn_frame, text="發(fā)送壁紙",
command=self.send_wallpaper)
send_btn.pack(side=tk.LEFT, padx=5)
# 測(cè)試連接按鈕
test_btn = ttk.Button(btn_frame, text="測(cè)試連接",
command=self.test_connection)
test_btn.pack(side=tk.LEFT, padx=5)
# 狀態(tài)欄
self.status_var = tk.StringVar()
self.status_var.set("就緒")
status_bar = ttk.Label(main_frame, textvariable=self.status_var,
relief=tk.SUNKEN, anchor=tk.W)
status_bar.pack(fill=tk.X, side=tk.BOTTOM)
def select_wallpaper(self):
"""選擇壁紙圖片"""
file_types = [
("圖片文件", "*.jpg *.jpeg *.png *.bmp"),
("所有文件", "*.*")
]
file_path = filedialog.askopenfilename(
title="選擇壁紙圖片",
filetypes=file_types
)
if file_path:
self.current_image_path = file_path
self.preview_wallpaper(file_path)
self.status_var.set(f"已選擇: {os.path.basename(file_path)}")
def preview_wallpaper(self, image_path):
"""預(yù)覽壁紙"""
try:
# 打開(kāi)圖片
image = Image.open(image_path)
# 調(diào)整圖片大小以適應(yīng)預(yù)覽區(qū)域
preview_width = 400
preview_height = 200
image.thumbnail((preview_width, preview_height), Image.Resampling.LANCZOS)
# 轉(zhuǎn)換為T(mén)kinter可用的格式
photo = ImageTk.PhotoImage(image)
# 更新預(yù)覽標(biāo)簽
self.preview_label.configure(image=photo, text="")
self.preview_label.image = photo # 保持引用
except Exception as e:
self.preview_label.configure(image=None, text="預(yù)覽加載失敗")
print(f"預(yù)覽圖片失敗: {e}")
def test_connection(self):
"""測(cè)試與目標(biāo)計(jì)算機(jī)的連接"""
ip = self.ip_entry.get().strip()
port = self.port_entry.get().strip()
if not ip:
messagebox.showerror("錯(cuò)誤", "請(qǐng)輸入目標(biāo)IP地址")
return
try:
port = int(port)
except ValueError:
messagebox.showerror("錯(cuò)誤", "端口號(hào)必須是數(shù)字")
return
try:
# 嘗試連接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5) # 5秒超時(shí)
result = sock.connect_ex((ip, port))
sock.close()
if result == 0:
messagebox.showinfo("成功", f"成功連接到 {ip}:{port}")
self.status_var.set(f"已連接到 {ip}:{port}")
else:
messagebox.showerror("錯(cuò)誤", f"無(wú)法連接到 {ip}:{port},請(qǐng)檢查目標(biāo)計(jì)算機(jī)是否運(yùn)行了服務(wù)端程序")
self.status_var.set("連接失敗")
except Exception as e:
messagebox.showerror("錯(cuò)誤", f"連接測(cè)試失敗: {str(e)}")
self.status_var.set("連接測(cè)試失敗")
def send_wallpaper(self):
"""發(fā)送壁紙到目標(biāo)計(jì)算機(jī)"""
# 獲取目標(biāo)IP和端口
ip = self.ip_entry.get().strip()
port = self.port_entry.get().strip()
if not ip:
messagebox.showerror("錯(cuò)誤", "請(qǐng)輸入目標(biāo)IP地址")
return
if not self.current_image_path:
messagebox.showerror("錯(cuò)誤", "請(qǐng)先選擇壁紙圖片")
return
try:
port = int(port)
except ValueError:
messagebox.showerror("錯(cuò)誤", "端口號(hào)必須是數(shù)字")
return
try:
# 讀取圖片文件
with open(self.current_image_path, 'rb') as f:
image_data = f.read()
# 獲取文件名
filename = os.path.basename(self.current_image_path)
# 創(chuàng)建連接
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10) # 10秒超時(shí)
self.status_var.set(f"正在連接到 {ip}:{port}...")
sock.connect((ip, port))
# 發(fā)送文件名和文件大小
file_info = {
'filename': filename,
'filesize': len(image_data)
}
file_info_json = json.dumps(file_info).encode('utf-8')
# 先發(fā)送文件信息長(zhǎng)度,然后發(fā)送文件信息
sock.send(len(file_info_json).to_bytes(4, byteorder='big'))
sock.send(file_info_json)
# 發(fā)送圖片數(shù)據(jù)
self.status_var.set("正在發(fā)送壁紙數(shù)據(jù)...")
sock.sendall(image_data)
# 接收響應(yīng)
response = sock.recv(1024).decode('utf-8')
sock.close()
if response == "SUCCESS":
messagebox.showinfo("成功", f"壁紙已成功發(fā)送到 {ip}")
self.status_var.set(f"壁紙已發(fā)送到 {ip}")
else:
messagebox.showerror("錯(cuò)誤", f"設(shè)置壁紙失敗: {response}")
self.status_var.set("設(shè)置壁紙失敗")
except Exception as e:
messagebox.showerror("錯(cuò)誤", f"發(fā)送壁紙失敗: {str(e)}")
self.status_var.set("發(fā)送失敗")
def main():
# 檢查依賴(lài)
try:
from PIL import Image
except ImportError:
print("請(qǐng)先安裝 Pillow 庫(kù): pip install Pillow")
return
# 創(chuàng)建主窗口
root = tk.Tk()
app = RemoteWallpaperClient(root)
# 啟動(dòng)主循環(huán)
root.mainloop()
if __name__ == "__main__":
main()
2. 接收端代碼
import os
import socket
import threading
import ctypes
import json
import tempfile
class WallpaperServer:
def __init__(self, port=12345):
self.port = port
self.host = '0.0.0.0' # 監(jiān)聽(tīng)所有接口
self.running = False
self.server_socket = None
def start(self):
"""啟動(dòng)服務(wù)器"""
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
self.running = True
print(f"壁紙服務(wù)器已啟動(dòng),監(jiān)聽(tīng)端口 {self.port}")
print("等待客戶(hù)端連接...")
while self.running:
try:
client_socket, addr = self.server_socket.accept()
print(f"接收到來(lái)自 {addr} 的連接")
# 為每個(gè)客戶(hù)端創(chuàng)建新線(xiàn)程
client_thread = threading.Thread(
target=self.handle_client,
args=(client_socket, addr)
)
client_thread.daemon = True
client_thread.start()
except Exception as e:
if self.running:
print(f"接受連接時(shí)出錯(cuò): {e}")
except Exception as e:
print(f"啟動(dòng)服務(wù)器失敗: {e}")
def handle_client(self, client_socket, addr):
"""處理客戶(hù)端連接"""
try:
# 接收文件信息長(zhǎng)度
file_info_len = int.from_bytes(client_socket.recv(4), byteorder='big')
# 接收文件信息
file_info_json = client_socket.recv(file_info_len).decode('utf-8')
file_info = json.loads(file_info_json)
filename = file_info['filename']
filesize = file_info['filesize']
print(f"接收文件: {filename}, 大小: {filesize} 字節(jié)")
# 接收文件數(shù)據(jù)
received_data = b''
while len(received_data) < filesize:
chunk = client_socket.recv(min(4096, filesize - len(received_data)))
if not chunk:
break
received_data += chunk
# 保存文件到臨時(shí)目錄
temp_dir = tempfile.gettempdir()
temp_file_path = os.path.join(temp_dir, filename)
with open(temp_file_path, 'wb') as f:
f.write(received_data)
print(f"文件已保存到: {temp_file_path}")
# 設(shè)置壁紙
if self.set_windows_wallpaper(temp_file_path):
print("壁紙?jiān)O(shè)置成功")
client_socket.send("SUCCESS".encode('utf-8'))
else:
print("壁紙?jiān)O(shè)置失敗")
client_socket.send("FAILED: 無(wú)法設(shè)置壁紙".encode('utf-8'))
except Exception as e:
print(f"處理客戶(hù)端請(qǐng)求時(shí)出錯(cuò): {e}")
try:
client_socket.send(f"FAILED: {str(e)}".encode('utf-8'))
except:
pass
finally:
client_socket.close()
def set_windows_wallpaper(self, image_path):
"""設(shè)置Windows壁紙"""
try:
# 轉(zhuǎn)換為絕對(duì)路徑
abs_path = os.path.abspath(image_path)
# Windows API 常量
SPI_SETDESKWALLPAPER = 20
SPIF_UPDATEINIFILE = 0x01
SPIF_SENDWININICHANGE = 0x02
# 設(shè)置壁紙
result = ctypes.windll.user32.SystemParametersInfoW(
SPI_SETDESKWALLPAPER,
0,
abs_path,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE
)
return bool(result)
except Exception as e:
print(f"設(shè)置壁紙失敗: {e}")
return False
def stop(self):
"""停止服務(wù)器"""
self.running = False
if self.server_socket:
self.server_socket.close()
print("壁紙服務(wù)器已停止")
def main():
# 檢查操作系統(tǒng)
if os.name != 'nt':
print("此程序僅支持Windows系統(tǒng)")
return
# 創(chuàng)建并啟動(dòng)服務(wù)器
server = WallpaperServer(port=12345)
try:
server.start()
except KeyboardInterrupt:
print("\n正在停止服務(wù)器...")
server.stop()
if __name__ == "__main__":
main()
系統(tǒng)效果展示
發(fā)送端界面

發(fā)送端提供直觀(guān)的GUI界面,包含以下功能區(qū)域:
目標(biāo)計(jì)算機(jī)設(shè)置
- IP地址輸入框(默認(rèn)192.168.1.)
- 端口輸入框(默認(rèn)12345)
壁紙?jiān)O(shè)置
- 選擇壁紙圖片按鈕
- 圖片預(yù)覽區(qū)域
- 支持JPG、JPEG、PNG、BMP格式
操作按鈕
- 發(fā)送壁紙按鈕
- 測(cè)試連接按鈕
- 實(shí)時(shí)狀態(tài)顯示欄
接收端運(yùn)行效果
接收端在后臺(tái)運(yùn)行,控制臺(tái)顯示如下?tīng)顟B(tài)信息:
壁紙服務(wù)器已啟動(dòng),監(jiān)聽(tīng)端口 12345 等待客戶(hù)端連接... 接收到來(lái)自 192.168.1.100 的連接 接收文件: wallpaper.jpg, 大小: 2048576 字節(jié) 文件已保存到: C:\Users\Username\AppData\Local\Temp\wallpaper.jpg 壁紙?jiān)O(shè)置成功
壁紙?jiān)O(shè)置效果

使用說(shuō)明
安裝依賴(lài)
在運(yùn)行程序前,需要安裝必要的Python庫(kù):
pip install Pillow
使用步驟
啟動(dòng)接收端:
- 在目標(biāo)計(jì)算機(jī)上運(yùn)行接收端程序
- 程序?qū)⒃诤笈_(tái)監(jiān)聽(tīng)指定端口(默認(rèn)12345)
- 僅支持Windows系統(tǒng)
配置發(fā)送端:
- 運(yùn)行發(fā)送端程序
- 輸入目標(biāo)計(jì)算機(jī)的IP地址
- 確保端口號(hào)與接收端一致
選擇壁紙:
- 點(diǎn)擊"選擇壁紙圖片"按鈕
- 從本地選擇圖片文件
- 預(yù)覽區(qū)域?qū)@示縮略圖
發(fā)送壁紙:
- 可先點(diǎn)擊"測(cè)試連接"驗(yàn)證網(wǎng)絡(luò)連通性
- 點(diǎn)擊"發(fā)送壁紙"開(kāi)始傳輸
- 狀態(tài)欄顯示發(fā)送進(jìn)度和結(jié)果
技術(shù)特點(diǎn)
網(wǎng)絡(luò)通信
- TCP協(xié)議:使用可靠的TCP連接傳輸文件
- 多線(xiàn)程處理:服務(wù)端為每個(gè)客戶(hù)端連接創(chuàng)建獨(dú)立線(xiàn)程
- JSON數(shù)據(jù)格式:使用JSON傳輸文件元信息
- 大文件支持:分塊傳輸,支持大尺寸圖片
文件處理
- 格式支持:支持常見(jiàn)圖片格式(JPG、PNG、BMP等)
- 預(yù)覽功能:發(fā)送端提供圖片預(yù)覽
- 臨時(shí)存儲(chǔ):接收端將文件保存在臨時(shí)目錄
- 路徑處理:自動(dòng)處理絕對(duì)路徑和相對(duì)路徑
Windows集成
- 系統(tǒng)API:使用Windows API設(shè)置壁紙
- 即時(shí)生效:壁紙?jiān)O(shè)置后立即應(yīng)用
- 兼容性:支持各種分辨率和圖片比例
應(yīng)用場(chǎng)景
企業(yè)環(huán)境
- 統(tǒng)一壁紙:為辦公電腦設(shè)置統(tǒng)一的公司壁紙
- 活動(dòng)宣傳:推送活動(dòng)主題壁紙
- 安全提醒:設(shè)置安全提示壁紙
教育場(chǎng)景
- 教室管理:為機(jī)房電腦統(tǒng)一設(shè)置壁紙
- 課程主題:根據(jù)課程內(nèi)容推送相關(guān)壁紙
家庭使用
- 多設(shè)備同步:為家中多臺(tái)電腦設(shè)置相同壁紙
- 節(jié)日主題:根據(jù)節(jié)日推送相應(yīng)主題壁紙
個(gè)人使用
- 遠(yuǎn)程管理:遠(yuǎn)程為自己的其他設(shè)備更換壁紙
- 自動(dòng)輪換:結(jié)合腳本實(shí)現(xiàn)自動(dòng)壁紙輪換
安全考慮
- 網(wǎng)絡(luò)隔離:建議在內(nèi)部網(wǎng)絡(luò)使用,或配置防火墻規(guī)則
- 身份驗(yàn)證:生產(chǎn)環(huán)境可添加簡(jiǎn)單的密碼驗(yàn)證
- 文件驗(yàn)證:可添加文件類(lèi)型和大小檢查
- 訪(fǎng)問(wèn)控制:可限制允許連接的IP地址范圍
擴(kuò)展功能
系統(tǒng)可以進(jìn)一步擴(kuò)展以下功能:
- 批量發(fā)送到多個(gè)目標(biāo)
- 壁紙定時(shí)自動(dòng)更換
- 壁紙歷史記錄和回滾
- 支持更多圖片格式和特效
- 添加用戶(hù)認(rèn)證機(jī)制
這個(gè)遠(yuǎn)程壁紙?jiān)O(shè)置系統(tǒng)展示了如何使用Python的socket編程和Windows API實(shí)現(xiàn)實(shí)用的系統(tǒng)集成功能。代碼結(jié)構(gòu)清晰,易于理解和擴(kuò)展,為跨設(shè)備文件傳輸和系統(tǒng)設(shè)置提供了很好的參考實(shí)現(xiàn)。
以上就是使用Python實(shí)現(xiàn)一個(gè)遠(yuǎn)程壁紙?jiān)O(shè)置系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于Python遠(yuǎn)程壁紙?jiān)O(shè)置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python中讀寫(xiě)Kafka隊(duì)列的實(shí)現(xiàn)示例
本文介紹了在Python中使用kafka-python庫(kù)連接和操作Kafka隊(duì)列,包括生產(chǎn)者發(fā)送消息到主題及消費(fèi)者從主題讀取消息的基本步驟, 感興趣的可以了解一下2025-12-12
NumPy實(shí)現(xiàn)廣播機(jī)制與廣播規(guī)則的示例
NumPy中的廣播機(jī)制,這是一種允許不同形狀數(shù)組之間進(jìn)行逐元素運(yùn)算的技術(shù),本文就來(lái)詳細(xì)的介紹一下NumPy實(shí)現(xiàn)廣播機(jī)制與廣播規(guī)則的示例,感興趣的可以了解一下2026-05-05
Pycharm配置opencv與numpy的實(shí)現(xiàn)
本文總結(jié)了兩種方法來(lái)導(dǎo)入opencv與numpy包,第一種是直接在Pycharm中導(dǎo)入兩個(gè)包,第二種是在官網(wǎng)下載相關(guān)文件進(jìn)行配置,感興趣的小伙伴們可以參考一下2021-07-07
YUV轉(zhuǎn)為jpg圖像的實(shí)現(xiàn)
今天小編就為大家分享一篇YUV轉(zhuǎn)為jpg圖像的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
使用jupyter notebook運(yùn)行python和R的步驟
這篇文章主要介紹了使用jupyter notebook運(yùn)行python和R的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
Spark處理數(shù)據(jù)排序問(wèn)題如何避免OOM
這篇文章主要介紹了Spark處理數(shù)據(jù)排序問(wèn)題如何避免OOM,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05

