用python做的windows动态天气壁纸

最近工作比较闲,做点东西娱乐一下。

之前看到酷狗的动态壁纸,挺炫酷的,还能自定义,可惜我不会html,于是查了查发现python也能做,嘿嘿!

原理基本就是用windowsAPI获取桌面窗口句柄,然后用自己的程序窗口替换掉就行,代码如下:

def getWindowHandle():
    hwnd = win32.win32gui.FindWindow("Progman", "Program Manager")
    win32.win32gui.SendMessageTimeout(hwnd, 0x052C, 0, None, 0, 0x03E8)
    hwnd_WorkW = None
    while 1:
        hwnd_WorkW = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        # print('hwmd_workw: ', hwnd_WorkW)
        if not hwnd_WorkW:
            continue
        hView = win32.win32gui.FindWindowEx(hwnd_WorkW, None, "SHELLDLL_DefView", None)
        # print('hwmd_hView: ', hView)
        if not hView:
            continue
        h = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        # print('h_1: ',h)
        while h:
            win32.win32gui.SendMessage(h, 0x0010, 0, 0)  # WM_CLOSE
            h = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
            # print(h)
        break
    return hwnd

动态准备用gif图像,简单,相关资源还多一些。

窗口用pyqt来做,可以方便的加载gif图像,还可以顺便加个托盘,方便退出,主要代码如下:

class QtWindow(QMainWindow):
    def __init__(self, parent=None):
        super(QtWindow, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)
        #self.setAttribute(Qt.WA_TranslucentBackground)

        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)

        self.gif_label = QLabel(self)

        win_hwnd = int(self.winId())
        h = win32.win32gui.FindWindow(("Progman"), ("Program Manager"))
        win32.win32gui.SetParent(win_hwnd, h)

然后就是获取当地的实时天气了,这个困扰了我一段时间,网上基本是两种方式,一种是申请一些开放平台的api来获取天气,一种是访问一些天气网站然后来爬取数据分析。本来不想用第一种方式,因为还得申请,可是用第二种方式折腾了好久,不是网址失效,就是被限制,最终还是用了开放平台的api。

申请了高德的,还是比较方便的,个人开发者也够用了。使用python的requests库访问对应网址获取天气。由于高德要求使用城市的adcode来获取对应的天气,所以要先获取当地城市adcode,再获取天气,代码如下:

def get_weather(self):
        url = "https://restapi.amap.com/v3/ip"
        params = {
            'key': 'your key',
        }

        response = requests.get(url, params=params)
        result = response.json()
        city_code = result['adcode']

        params = {
            'key': 'your key',
            'city': city_code
        } 

        response = requests.get('https://restapi.amap.com/v3/weather/weatherInfo?parameters', params=params)
        result = response.json()
 
        # 提取所需的天气信息
        if result['status'] == '1' and int(result['count']) >= 1:
            weather_info = result['lives'][0]
            weather_info = weather_info['weather']
            if weather_info not in gaode_weathers:
                self.weather_info_signal.emit('未知')
            #print("天气状态:", weather_info['weather'])
            else:
                self.weather_info_signal.emit(weather_info)
        else:
            #print("无法获取到天气信息!")
            self.weather_info_signal.emit('未知')

由高德得到的天气状态是个中文字符,比如“晴”,“多云”,“小雪”等等,查了下,高德一共有68种天气状态,我们要为每一种天气状态都配一个gif图(找gif图简直是个噩梦),然后获取到天气状态后显示对应的gif图即可。

然后就是用qt的QTimer做定时器,每半个小时获取一次天气,然后更新壁纸;做一个托盘,方便退出。

所有代码都贴一下:

#weather_wallpaper.py

import sys
import os

import win32.win32gui
from PyQt5.QtWidgets import *

from qtwindow import QtWindow
from Weather import Weather

from PyQt5.QtWidgets import QApplication, QWidget, QSystemTrayIcon, QAction, QMenu
from PyQt5.QtGui import QIcon, QPixmap, QColor

class TaryWiondw(QWidget):
    def __init__(self):
        super().__init__()
        # 创建托盘对象
        self.tray = QSystemTrayIcon()

        #self.trayIconPix = QPixmap(16,16)
        #self.trayIconPix.fill(QColor(255,0,123))
        icopath = 'res//天气.png'
        bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(icopath)))
        path = os.path.join(bundle_dir, icopath)
        self.trayIconPix = QPixmap(path)
        self.Icon = QIcon(self.trayIconPix)

        self.tray.setIcon(self.Icon)

        #showAction = QAction("&Show", self, triggered = self.Show)
        quitAction = QAction("&Quit", self, triggered = self.Exit)
        self.trayMenu = QMenu(self)
        #self.trayMenu.addAction(showAction)
        self.trayMenu.addSeparator()
        self.trayMenu.addAction(quitAction)
        self.tray.setContextMenu(self.trayMenu)
        self.tray.show()

    def Exit(self):
        self.tray = None
        sys.exit(app.exec_())

    def Show(self):
        #self.show()
        a = 0

def getWindowHandle():
    hwnd = win32.win32gui.FindWindow("Progman", "Program Manager")
    win32.win32gui.SendMessageTimeout(hwnd, 0x052C, 0, None, 0, 0x03E8)
    hwnd_WorkW = None
    while 1:
        hwnd_WorkW = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        # print('hwmd_workw: ', hwnd_WorkW)
        if not hwnd_WorkW:
            continue
        hView = win32.win32gui.FindWindowEx(hwnd_WorkW, None, "SHELLDLL_DefView", None)
        # print('hwmd_hView: ', hView)
        if not hView:
            continue
        h = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        # print('h_1: ',h)
        while h:
            win32.win32gui.SendMessage(h, 0x0010, 0, 0)  # WM_CLOSE
            h = win32.win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
            # print(h)
        break
    return hwnd


if __name__ == "__main__":
    app = QApplication(sys.argv)
    getWindowHandle()
    weather = Weather()
    myWin = QtWindow()
    weather.weather_info_signal.connect(myWin.recvWeather_slot)
    myWin.showFullScreen()
    weather.get_weather()
    w = TaryWiondw()
    sys.exit(app.exec_())



#Weather.py

import requests

from PyQt5.QtCore import QObject, pyqtSignal, QTimer

gaode_weathers = ['晴', '少云', '晴间多云', '多云', '阴', '有风', '平静', 
'微风','和风','清风','强风-劲风','疾风','大风','烈风','风暴','狂爆风','飓风','热带风暴','霾','中度霾','重度霾','严重霾',
'阵雨','雷阵雨','雷阵雨并伴有冰雹','小雨','中雨','大雨','暴雨','大暴雨','特大暴雨','强阵雨','强雷阵雨','极端降雨','毛毛雨-细雨',
'雨','小雨-中雨','中雨-大雨','大雨-暴雨','暴雨-大暴雨','大暴雨-特大暴雨','雨雪天气','雨夹雪','阵雨夹雪','冻雨','雪','阵雪',
'小雪','中雪','大雪','暴雪','小雪-中雪','中雪-大雪','大雪-暴雪','浮尘','扬沙','沙尘暴','强沙尘暴','龙卷风','雾','浓雾','强浓雾',
'轻雾','大雾','特强浓雾','热','冷','未知']

class Weather(QObject):
    weather_info_signal = pyqtSignal(str)

    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        self.weatherTimer = QTimer()
        self.weatherTimer.timeout.connect(self.get_weather)
        self.weatherTimer.start(1800000)
        
    def get_weather(self):
        url = "https://restapi.amap.com/v3/ip"
        params = {
            'key': 'your key',
        }

        response = requests.get(url, params=params)
        result = response.json()
        city_code = result['adcode']

        params = {
            'key': 'your key',
            'city': city_code
        } 

        response = requests.get('https://restapi.amap.com/v3/weather/weatherInfo?parameters', params=params)
        result = response.json()
 
        # 提取所需的天气信息
        if result['status'] == '1' and int(result['count']) >= 1:
            weather_info = result['lives'][0]
            weather_info = weather_info['weather']
            if weather_info not in gaode_weathers:
                self.weather_info_signal.emit('未知')
            #print("天气状态:", weather_info['weather'])
            else:
                self.weather_info_signal.emit(weather_info)
        else:
            #print("无法获取到天气信息!")
            self.weather_info_signal.emit('未知')

    
#qtWindow.py

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QMovie

import win32.win32gui
import sys
import os

class QtWindow(QMainWindow):
    def __init__(self, parent=None):
        super(QtWindow, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)
        #self.setAttribute(Qt.WA_TranslucentBackground)

        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)

        self.gif_label = QLabel(self)

        win_hwnd = int(self.winId())
        h = win32.win32gui.FindWindow(("Progman"), ("Program Manager"))
        win32.win32gui.SetParent(win_hwnd, h)

    def recvWeather_slot(self, weather_info):
        gifpath = 'res//' + weather_info + '.gif'
        bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(gifpath)))
        path = os.path.join(bundle_dir, gifpath)
        self.startGif(path)

    def startGif(self, path):
        self.gif = QMovie(path)
        if self.gif is not None:
            self.gif_label.setMovie(self.gif)
            screen = QDesktopWidget().screenGeometry()
            desktop_size = screen.size()
            self.gif.setScaledSize(screen.size())
            self.gif_label.setGeometry(0,0,desktop_size.width(),desktop_size.height())
            self.gif.start()

    def stopGif(self):
        self.gif.stop()
            

打包exe可以用pyinstaller将gif图也打包进去,具体可以参考https://blog.csdn.net/fullback555/article/details/104621530,还可以设置把命令行窗口也去掉,基本就完美了。

懒得找资源的可以从这里(https://download.csdn.net/download/ntw516/88628658)下载,只是需要申请高德平台的api-key填到key.txt里。另外,我找到的资源也不咋好,分辨率低,有的还有水印。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值