前言
前段時間,用PyQt5寫了幾篇文章,自己用python做的一款超炫酷音樂播放器、用Python做個個性的動畫掛件讓桌面不單調(diào)、詳細過程帶你用Python做車牌自動識別系統(tǒng)。今天就繼續(xù)給大家分享一個實戰(zhàn)案例,帶大家一起用Python的PyQt5開發(fā)一個自定義動態(tài)桌面壁紙,好玩又有趣!
首先一起來看看最終實現(xiàn)的自定義動態(tài)壁紙效果:
下
面,我們開始介紹這個自定義動態(tài)桌面的制作過程。
一、核心功能設計
總體來說,我們需要實現(xiàn)將自己喜歡的視頻轉成一個動態(tài)桌面,知識點主要包含了對視頻提取解析,視頻輪播,PyQt5窗體設置,桌面句柄獲取,自定義動態(tài)桌面壁紙實現(xiàn)等。
拆解需求,大致可以整理出我們需要分為以下幾步完成:
-
UI排版布局設計,確認動態(tài)壁紙功能設計 加載視頻,對視頻進行預覽讀取,保存視頻路徑等 動態(tài)壁紙功能實現(xiàn)應用,獲取桌面句柄,輪播加載視頻 關閉動態(tài)壁紙,在線壁紙資源獲取等
二、實現(xiàn)步驟
之前有粉絲反饋說,想自己跟著文章自己敲敲代碼,但是不知道具體需要哪些模塊、包文件,后面我就把所有用到模塊先放出來。
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排版布局設計
根據(jù)動態(tài)壁紙所需要的功能,首先進行UI布局設計,我們這次還是使用的pyqt5。主要包含了加載讀取本地視頻、視頻加載預覽、動態(tài)壁紙應用、動態(tài)壁紙關閉等。核心設計代碼如下:
# 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() # 創(chuàng)建左側部件的網(wǎng)格布局層 self.close_widget.setLayout(self.close_layout) # 設置左側部件布局為網(wǎng)格 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實現(xiàn)效果如下:
UI布局設計完成,下面我們開始進行視頻讀取加載、預覽功能實現(xiàn)。
2. 視頻加載預覽
接來下我們可以根據(jù)自己喜歡的視頻,從本地讀取視頻,并且將視頻預覽播放顯示。這里視頻演示,博主還是用之前的那篇紫顏小姐姐的跳舞視頻進行演示。
讀取視頻:
讀取視頻我們可以通過打開文件對話框,選擇視頻資源,開啟一個子線程用來進行視頻開啟停止播放。核心代碼如下:
# 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() # 啟動線程,即讓線程開始執(zhí)行 except Exception as e: print (e)
視頻流讀取播放:
接下來,我們需要對視頻文件進行按幀讀取加載顯示,并通過計時器實現(xiàn)動畫效果。核心代碼如下:
# 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() # 停止計時器
至此,我們已經(jīng)可以實現(xiàn)視頻讀取加載,并且進行視頻預覽了,效果如下:
3. 動態(tài)壁紙功能實現(xiàn)
實現(xiàn)桌面壁紙?zhí)鎿Q,我們首先需要獲取桌面句柄找到桌面窗體,覆寫桌面窗體、調(diào)用加載的視頻流,播放動態(tài)壁紙。
獲取桌面句柄:
# 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
桌面覆寫:
我們可以創(chuàng)建一個類,對窗體進行繼承,進行視頻流加載讀取播放。核心代碼如下:
# 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文件,接下來我們在“應用”控件上進行事件綁定,直接調(diào)用exe執(zhí)行,實現(xiàn)動態(tài)壁紙播放應用功能。核心代碼如下:
# 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
這樣,我們就完成了動態(tài)壁紙加載應用功能了,效果如下:
4. 關閉動態(tài)壁紙
最后我們再實現(xiàn)下當前動態(tài)壁紙播放關閉功能,我們需要對當前桌面視頻播放進行釋放取消。代碼如下:
# author:CSDN-Dragon少年 def close_wall(self): try: call('taskkill /F /IM play.exe') except: pass
效果如下:
至此,整個自定義動態(tài)桌面壁紙功能就全部完成了,下面我們一起運行下看看動態(tài)壁紙效果。
今天我們就到這里,明天繼續(xù)努力!
到此這篇關于Python做個自定義動態(tài)壁紙還可以放視頻的文章就介紹到這了,更多相關Python動態(tài)視頻壁紙內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/hhladminhhl/article/details/119902562