桌面太单调?一起用Python做个自定义动态壁纸,竟然还可以放视频!「建议收藏」

桌面太单调?一起用Python做个自定义动态壁纸,竟然还可以放视频!「建议收藏」前言前段时间,用PyQt5写了几篇文章,关于Python自制一款炫酷音乐播放器、自定义桌面动画挂件、车牌自动识别系统。今天就继续给大家分享一个实战案例,带大家一起用Python的PyQt5开发一个自定义动态桌面壁纸,好玩又有趣!首先一起来看看最终实现的自定义动态壁纸效果:…

大家好,又见面了,我是你们的朋友全栈君。

前言

前段时间,用PyQt5写了几篇文章,关于Python自制一款炫酷音乐播放器自定义桌面动画挂件车牌自动识别系统。今天就继续给大家分享一个实战案例,带大家一起用Python的PyQt5开发一个自定义动态桌面壁纸,好玩又有趣!

首先一起来看看最终实现的自定义动态壁纸效果:
在这里插入图片描述
下面,我们开始介绍这个自定义动态桌面的制作过程。

直接跳到文末获取粉丝专属福利。

一、核心功能设计

总体来说,我们需要实现将自己喜欢的视频转成一个动态桌面,知识点主要包含了对视频提取解析视频轮播PyQt5窗体设置桌面句柄获取自定义动态桌面壁纸实现等。

拆解需求,大致可以整理出我们需要分为以下几步完成:

  1. UI排版布局设计,确认动态壁纸功能设计
  2. 加载视频,对视频进行预览读取,保存视频路径等
  3. 动态壁纸功能实现应用,获取桌面句柄,轮播加载视频
  4. 关闭动态壁纸,在线壁纸资源获取等

二、实现步骤

之前有粉丝反馈说,想自己跟着文章自己敲敲代码,但是不知道具体需要哪些模块、包文件,后面我就把所有用到模块先放出来。

import os
import sys
from subprocess import call
from threading import Thread
from time import sleep

import cv2
from PyQt5 import QtCore,  QtWidgets
from PyQt5.QtCore import Qt,  QTimer
from PyQt5.QtGui import QImage, QPixmap, QIcon

from PyQt5.QtWidgets import QGridLayout, QPushButton, QMainWindow, QFileDialog, QLabel, QSystemTrayIcon, \
    QAction, QMenu, QMessageBox
from os import path as pathq

1. UI排版布局设计

根据动态壁纸所需要的功能,首先进行UI布局设计,我们这次还是使用的pyqt5。主要包含了加载读取本地视频、视频加载预览、动态壁纸应用、动态壁纸关闭等。核心设计代码如下:

# author:CSDN-Dragon少年
def setupUi(self, MainWindow):
    MainWindow.setObjectName("MainWindow")
    MainWindow.resize(505, 615)
    MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
    self.centralwidget = QtWidgets.QWidget(MainWindow)
    self.centralwidget.setObjectName("centralwidget")
    self.pushButton = QtWidgets.QPushButton(self.centralwidget)
    self.pushButton.setGeometry(QtCore.QRect(22, 10, 89, 31))
    self.pushButton.setObjectName("pushButton")
    self.pushButton.clicked.connect(self.openmp4)
    self.pushButton.setStyleSheet(
        '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''')
    self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
    self.groupBox.setGeometry(QtCore.QRect(22, 50, 452, 351))
    self.groupBox.setObjectName("groupBox")
    self.widget = QtWidgets.QWidget(self.groupBox)
    self.widget.setGeometry(QtCore.QRect(11, 20, 430, 291))
    self.widget.setObjectName("widget")
    self.gridLayout_3 = QtWidgets.QGridLayout(self.widget)
    self.gridLayout_3.setObjectName("gridLayout_3")
    self.label = QLabel(self)
    self.label.resize(400, 300)
    self.label.setText("Waiting for video...")
    self.gridLayout_3.addWidget(self.label)
    self.close_widget = QtWidgets.QWidget(self.centralwidget)
    self.close_widget.setGeometry(QtCore.QRect(420, 0, 93, 41))
    self.close_widget.setObjectName("close_widget")
    self.close_layout = QGridLayout()  # 创建左侧部件的网格布局层
    self.close_widget.setLayout(self.close_layout)  # 设置左侧部件布局为网格
    self.left_close = QPushButton("")  # 关闭按钮
    self.left_close.clicked.connect(self.close)
    self.left_visit = QPushButton("")  # 空白按钮
    #self.left_visit.clicked.connect(MainWindow.big)
    self.left_mini = QPushButton("")  # 最小化按钮
    self.left_mini.clicked.connect(MainWindow.mini)
    self.close_layout.addWidget(self.left_mini, 0, 0, 1, 1)
    self.close_layout.addWidget(self.left_close, 0, 2, 1, 1)
    self.close_layout.addWidget(self.left_visit, 0, 1, 1, 1)
    self.left_close.setFixedSize(15, 15)  # 设置关闭按钮的大小
    self.left_visit.setFixedSize(15, 15)  # 设置按钮大小
    self.left_mini.setFixedSize(15, 15)  # 设置最小化按钮大小
    self.left_close.setStyleSheet(
        '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''')
    self.left_visit.setStyleSheet(
        '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''')
    self.left_mini.setStyleSheet(
        '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''')
    self.horizontalLayout = QtWidgets.QHBoxLayout(self.close_widget)
    self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
    self.horizontalLayout.setObjectName("horizontalLayout")
    self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
    self.pushButton_2.setGeometry(QtCore.QRect(77, 440, 133, 41))
    self.pushButton_2.setObjectName("pushButton_2")
    self.pushButton_2.clicked.connect(self.play)
    self.pushButton_2.setStyleSheet(
        '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''')
    self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
    self.pushButton_3.setGeometry(QtCore.QRect(308, 440, 111, 41))
    self.pushButton_3.setObjectName("pushButton_3")
    self.pushButton_3.clicked.connect(self.close_wall)
    self.pushButton_3.setStyleSheet(
        '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''')
    self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
    self.pushButton_4.setGeometry(QtCore.QRect(187, 540, 133, 21))
    self.pushButton_4.setObjectName("pushButton_4")
    self.pushButton_4.clicked.connect(self.openurl)
    self.pushButton_4.setStyleSheet(
        '''QPushButton{background:#222225;color:white;border-radius:5px;}QPushButton:hover{background:#222225;color:skyblue}''')
    MainWindow.setCentralWidget(self.centralwidget)
    self.menubar = QtWidgets.QMenuBar(MainWindow)
    self.menubar.setGeometry(QtCore.QRect(0, 0, 505, 23))
    self.menubar.setObjectName("menubar")
    MainWindow.setMenuBar(self.menubar)
    self.statusbar = QtWidgets.QStatusBar(MainWindow)
    self.statusbar.setObjectName("statusbar")
    MainWindow.setStatusBar(self.statusbar)
    self.retranslateUi(MainWindow)
    QtCore.QMetaObject.connectSlotsByName(MainWindow)
    self.groupBox.setStyleSheet(''' color:white ''')
    MainWindow.setWindowOpacity(0.95)  # 设置窗口透明度
    MainWindow.setAttribute(Qt.WA_TranslucentBackground)
    MainWindow.setWindowFlag(Qt.FramelessWindowHint)  # 隐藏边框
# author:Dragon少年
def retranslateUi(self, MainWindow):
    _translate = QtCore.QCoreApplication.translate
    MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
    self.pushButton.setText(_translate("MainWindow", "从本地选择"))
    self.groupBox.setTitle(_translate("MainWindow", "预览"))
    self.pushButton_2.setText(_translate("MainWindow", "应用"))
    self.pushButton_3.setText(_translate("MainWindow", "关闭壁纸"))
    self.pushButton_4.setText(_translate("MainWindow", "在线资源"))

UI实现效果如下:
在这里插入图片描述
UI布局设计完成,下面我们开始进行视频读取加载、预览功能实现。

2. 视频加载预览

接来下我们可以根据自己喜欢的视频,从本地读取视频,并且将视频预览播放显示。这里视频演示,博主还是用之前的那篇紫颜小姐姐的跳舞视频进行演示。

读取视频:

读取视频我们可以通过打开文件对话框,选择视频资源,开启一个子线程用来进行视频开启停止播放。核心代码如下:

# author: CSDN-Dragon少年
def openmp4(self):
    try:
        global path
        path, filetype = QFileDialog.getOpenFileName(None, "选择文件", '.',
                                                     "视频文件(*.AVI;*.mov;*.rmvb;*.rm;*.FLV;*.mp4;*.3GP)")  # ;;All Files (*)
        if path == "":  # 未选择文件
            return

        self.slotStart()
        t = Thread(target=self.Stop)
        t.start()  # 启动线程,即让线程开始执行
    except Exception as e:
        print (e)

视频流读取播放:

接下来,我们需要对视频文件进行按帧读取加载显示,并通过计时器实现动画效果。核心代码如下:

# author:CSDN-Dragon少年
def slotStart(self):
    videoName = path
    if videoName != "":  # “”为用户取消
        self.cap = cv2.VideoCapture(videoName)
        self.timer_camera.start(50)
        self.timer_camera.timeout.connect(self.openFrame)
# author:CSDN-Dragon少年
def openFrame(self):
    if (self.cap.isOpened()):
        ret, self.frame = self.cap.read()
        if ret:
            frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
            if self.detectFlag == True:
                # 检测代码self.frame
                self.label_num.setText("There are " + str(5) + " people.")
            height, width, bytesPerComponent = frame.shape
            bytesPerLine = bytesPerComponent * width
            q_image = QImage(frame.data, width, height, bytesPerLine,
                             QImage.Format_RGB888).scaled(self.label.width(), self.label.height())
            self.label.setPixmap(QPixmap.fromImage(q_image))
        else:
            self.cap.release()
            self.timer_camera.stop()  # 停止计时器

至此,我们已经可以实现视频读取加载,并且进行视频预览了,效果如下:

在这里插入图片描述

3. 动态壁纸功能实现

实现桌面壁纸替换,我们首先需要获取桌面句柄找到桌面窗体,覆写桌面窗体、调用加载的视频流,播放动态壁纸。

获取桌面句柄:

# author:CSDN-Dragon少年
def pretreatmentHandle():
    hwnd = win32gui.FindWindow("Progman", "Program Manager")
    win32gui.SendMessageTimeout(hwnd, 0x052C, 0, None, 0, 0x03E8)
    hwnd_WorkW = None
    while 1:
        hwnd_WorkW = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        if not hwnd_WorkW:
            continue
        hView = win32gui.FindWindowEx(hwnd_WorkW, None, "SHELLDLL_DefView", None)
        # print('hwmd_hView: ', hView)
        if not hView:
            continue
        h = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        while h:
            win32gui.SendMessage(h, 0x0010, 0, 0)  # WM_CLOSE
            h = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        break
    return hwnd

桌面覆写:

我们可以创建一个类,对窗体进行继承,进行视频流加载读取播放。核心代码如下:

# author: CSDN-Dragon少年
class MyMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.player = QMediaPlayer()
        self.player.setNotifyInterval(10000)
        self.player.setVideoOutput(self.ui.videowidget)
        self.player.setMuted(bool(1 - self.player.isMuted()))
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setupUi(self)
        self.go()


	# author: CSDN-Dragon少年
    def go(self):
        self.ui.videowidget.setFullScreen(True)

        with open("./filename.txt", 'r', encoding='utf-8') as f:
            file_name = f.read()
            if file_name =='':
                file_name = 'lkf.mp4'
        print (file_name)
        if not os.path.exists(file_name):
            sys.exit()
        media = QMediaContent(QUrl(file_name))
        self.player.setMedia(media)
        self.mplayList = QMediaPlaylist()
        self.mplayList.addMedia(QMediaContent(QUrl.fromLocalFile(file_name)))
        self.player.setPlaylist(self.mplayList)
        self.mplayList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        win_hwnd = int(self.winId())
        video_h = int(self.ui.videowidget.winId())
        win32gui.SetParent(win_hwnd, h)
        win32gui.SetParent(video_h, h)
        win32gui.SetParent(video_h, win_hwnd)
        self.player.play()

这里我们把上面的py文件直接打包成exe文件,接下来我们在“应用”控件上进行事件绑定,直接调用exe执行,实现动态壁纸播放应用功能。核心代码如下:

# author: CSDN-Dragon少年
def play(self):
     if path == '':
         reply = QtWidgets.QMessageBox.question(self, '提示',
                                                "未加载选择视频",
                                                QtWidgets.QMessageBox.Yes)
         return
     with open("./filename.txt", 'w', encoding='utf-8') as f:
         f.truncate(0)
         print(f.write(str(path)))
     try:
         try:
             call('taskkill /F /IM play.exe')
         except:
             pass
         os.system('start play.exe')
     except:
         pass
     try:
         if self.cap != []:
             self.cap.release()
             self.timer_camera.stop()  # 停止计时器
         else:
             Warming = QMessageBox.warning(self, "Warming", "Push the left upper corner button to Quit.",
                                           QMessageBox.Yes)
     except:
         pass

这样,我们就完成了动态壁纸加载应用功能了,效果如下:
在这里插入图片描述

4. 关闭动态壁纸

最后我们再实现下当前动态壁纸播放关闭功能,我们需要对当前桌面视频播放进行释放取消。代码如下:

# author:CSDN-Dragon少年
 def close_wall(self):
     try:
         call('taskkill /F /IM play.exe')
     except:
         pass

效果如下:
在这里插入图片描述

至此,整个自定义动态桌面壁纸功能就全部完成了,下面我们一起运行下看看动态壁纸效果。

源码及数据已上传,关注文末公众号回复【源码】即可获取完整源码

Python往期精彩:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138343.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • HTML/CSS 常见面试题汇总

    HTML/CSS 常见面试题汇总HTML面试题1、<image>标签上title属性与alt属性的区别是什么?alt属性是为了给那些不能看到你文档中图像的浏览者提供文字说明的。且长度必须少于100个英文字符或者用户必须保证替换文字尽可能的短。这包括那些使用本来就不支持图像显示或者图像显示被关闭的浏览器的用户,视觉障碍的用户和使用屏幕阅读器的用户等。title属性为设置该属性的元素提供建议性的信息。使用ti…

  • 在线客服系统源码demo/PHP客服系统下载附php源码「建议收藏」

    在线客服系统源码demo/PHP客服系统下载附php源码「建议收藏」在线客服系统软件为每个客户提供个性化的一对一支持。在线客服系统源码安装实时聊天小部件在尽可能多的网站和博客上并可定制聊天小部件完全适合您的网站。从一系列颜色和选项混合搭配。在线客服系统附源码演示及下载地址:ym.ws58.net在线客服系统源码H5通过为常见答案和回复创建快捷方式来节省时间。基于thinkphp在网页线客服完整源码下载地址:ym.ws58.net在聊天室里点击一个按钮就可以看到这些,只需单击一次即可将聊天内容传送到其他代理。团队合作以取悦顾客。实时聊天小部件跟踪访问者浏览您.

  • 记一次使用策略模式优化代码的经历[通俗易懂]

    记一次使用策略模式优化代码的经历[通俗易懂]一、背景之前接手了一个springboot项目。在我负责的模块中,有一块用户注册的功能,但是比较特别的是这个注册并不是重新注册,而是从以前的旧系统的数据库中同步旧数据到新系统的数据库中。由于这些

  • Excel宏编程,给出2列进行去重合并

    Excel宏编程,给出2列进行去重合并Sub去重合并()arr=Worksheets(“sheet1”).Range(“D1”).Clear’选择D列作为存储列,保存最后去重合并的值arr=Worksheets(“sheet1”).UsedRangeDimARowAsLong’A列的行数DimBRowAsLong’B列的行数ARow=Sheet1.Range(“A”&Rows.Count).End(xlUp).Row’不带空格的行数BRow=Sheet1.Range..

  • vscode远程开发python_vscode版本

    vscode远程开发python_vscode版本在大二刚接触linux系统的时候,学校的服务器装的都是有图形界面Ubuntu系统,使用teamviewer远程连接操作很方便,就像多了个电脑一样。可是最近进所里后发现,给分配的服务器只有能使用ssh登录的终端,这让我这个被pycharm的各种功能惯坏了的人十分不爽,不能代码提示补全、不能一眼看到所有文件、不能随心所欲地debug。。。因此我开始了寻找舒适远程开发方法的无用功旅程,在此期间尝试了mobaxterm,vscode和pycharm。最后总结了下各个方法的使用情况。一、Mobaxter…

  • LVS:三种负载均衡方式比较+另三种负载均衡方式

    LVS:三种负载均衡方式比较+另三种负载均衡方式

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号