目录
简介
程序
源代码
GUI
DesktopWife.py
MusicPlayer.py
WeatherGui.py
语音
简介
普通的桌面宠物程序只能动一动,于是我给程序添加了语言,既可以聊天,也可以实现一些自动功能,不如搜索,打开程序什么的。
程序
源代码
gui界面都是使用PyQt5开发的,语音唤醒功能也是使用的第三方库和api
GUI
DesktopWife.py
import sys
import os
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QPainterPath
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QRectF
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QDesktopWidget
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QAction
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QMessageBox
import requests
import WeatherGui
import MusicPlayer
import Tray
import VoiceToText
VoiceToText.run()
"""主界面"""
class DesktopWife(QWidget):
def __init__(self):
super(DesktopWife, self).__init__()
self.UI()
def UI(self):
self.Image = QPixmap(".\image\\bg.png")
self.WindowSize = QDesktopWidget().screenGeometry()
self.setWindowTitle("DesktopWife")
self.resize(int(self.Image.width()), int(self.Image.height()))
self.move(int((self.WindowSize.width() - self.Image.width()) / 2), int((self.WindowSize.height() - self.Image.height()) / 2))
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.SubWindow)
# setAutoFillBackground(True)表示的是自动填充背景,False为透明背景
self.setAutoFillBackground(False)
# 窗口透明,窗体空间不透明
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.PlayLabel = QLabel(self)
self.PlayLabel.setPixmap(self.Image)
self.WindowMessage = QLabel("我好困", self)
self.WindowMessage.setGeometry(int((self.Image.width() - 80) / 2) + 10, 10, 200, 40)
self.WindowMessage.setStyleSheet("color: white;")
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self._WindowMenu)
self.Timer = QTimer()
self.Timer.start(5000)
self.Timer.timeout.connect(self.RandomWindowMessage)
"""右键菜单"""
def _WindowMenu(self):
self.Menu = QMenu(self)
self.Menu.setStyleSheet("background-color: black; color: white;")
self.WeatherForecastQAction = QAction(QIcon(".\image\Button.png"), u"查看天气", self)
self.Menu.addAction(self.WeatherForecastQAction)
self.PlayMusicQAction = QAction(QIcon(".\image\Button.png"), u"播放音乐", self)
self.Menu.addAction(self.PlayMusicQAction)
self.StartTray = QAction(QIcon(".\image\\bg.png"), u"退置托盘", self)
self.Menu.addAction(self.StartTray)
self.CloseWindowAction = QAction(QIcon(".\image\Quit.png"), u"退出程序", self)
self.Menu.addAction(self.CloseWindowAction)
self.WeatherForecastQAction.triggered.connect(self.WeatherForecast)
self.PlayMusicQAction.triggered.connect(self.MusicPaly)
self.StartTray.triggered.connect(self.SetTray)
self.CloseWindowAction.triggered.connect(self.ColseWindowActionEvent)
self.Menu.popup(QCursor.pos())
# 圆角
rect = QRectF(0, 0, self.Menu.width(), self.Menu.height())
path = QPainterPath()
path.addRoundedRect(rect, 10, 10)
polygon = path.toFillPolygon().toPolygon()
region = QRegion(polygon)
self.Menu.setMask(region)
def ColseWindowActionEvent(self):
VoiceToText._conent = False
self.close()
sys.exit()
"""系统托盘"""
def SetTray(self):
self._Tray = Tray.TrayIcon(self)
self._Tray.show()
self.hide()
"""随机一诗"""
"""音乐播放"""
def MusicPaly(self):
self.file, _Type = QFileDialog.getOpenFileName(self, u"选择音乐文件", f"{os.path.split(__file__)[0]}\\music")
if os.path.isfile(self.file):
self._MusicPlayGui = MusicPlayer.MusicGui(self.file)
self._MusicPlayGui.show()
else:
QMessageBox.information(self, "提示", f"文件:{self.file} 无法识别")
"""天气预报"""
def WeatherForecast(self):
self.WeatherForecastGUI = WeatherGui.WeatherGUI()
self.WeatherForecastGUI.show()
"""重写移动事假,更改鼠标图标"""
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_flag = True
self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_flag:
self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
QMouseEvent.accept()
def mouseReleaseEvent(self, QMouseEvent):
self.m_flag = False
self.setCursor(QCursor(Qt.ArrowCursor))
if __name__ == '__main__':
app = QApplication(sys.argv)
Window = DesktopWife()
Window.show()
app.exec_()
MusicPlayer.py
import os
from PyQt5 import QtMultimedia
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QPainterPath
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QSize
from PyQt5.QtCore import QRectF
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QSlider
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QPushButton
from mutagen import File
"""音乐播放界面"""
class MusicGui(QWidget):
def __init__(self, _file):
super(MusicGui, self).__init__()
self.file = _file
self.GetMusicIcon()
self.UI()
self.Music = QUrl.fromLocalFile(_file)
self.Content = QtMultimedia.QMediaContent(self.Music)
self.player = QtMultimedia.QMediaPlayer()
self.player.setVolume(100)
self.player.setMedia(self.Content)
def UI(self):
self.setWindowTitle("DesktopWife-MusicPlayGui")
self.resize(240, 135)
self.QuitButton = QPushButton(self)
self.QuitButton.setIcon(QIcon(".\image\MusicQuit.png"))
self.QuitButton.setIconSize(QSize(200, 200))
self.QuitButton.setGeometry(208, 10, 20, 20)
QuitButtonRect = QRectF(0, 0, self.QuitButton.width(), self.QuitButton.height())
QuitButtonPath = QPainterPath()
QuitButtonPath.addRoundedRect(QuitButtonRect, 10, 10)
QuitButtonPolgon = QuitButtonPath.toFillPolygon().toPolygon()
QuitButtonRegion = QRegion(QuitButtonPolgon)
self.QuitButton.setMask(QuitButtonRegion)
self.QuitButton.clicked.connect(self.QuitButtonEvent)
self.WindowMinimizedButton = QPushButton(self)
self.WindowMinimizedButton.setIcon(QIcon(".\image\WindowMinimized.png"))
self.WindowMinimizedButton.setIconSize(QSize(20, 20))
self.WindowMinimizedButton.setGeometry(180, 10, 20, 20)
WindowMinimizedButtonRect = QRectF(0, 0, self.WindowMinimizedButton.width(), self.WindowMinimizedButton.height())
WindowMinimizedButtonPath = QPainterPath()
WindowMinimizedButtonPath.addRoundedRect(WindowMinimizedButtonRect, 10, 10)
WindowMinimizedButtonPolgon = QuitButtonPath.toFillPolygon().toPolygon()
WindowMinimizedButtonRegion = QRegion(WindowMinimizedButtonPolgon)
self.WindowMinimizedButton.setMask(WindowMinimizedButtonRegion)
self.WindowMinimizedButton.clicked.connect(self.SetWindowMin)
self.MusicIconLabel = QPushButton(self)
self.MusicIconLabel.setGeometry(20, 20, 30, 30)
self.MusicIconLabel.setStyleSheet("color: blue;")
if os.path.isfile(".\music\MusicIcon\MusicIcon.jpg"):
self.MusicIconLabel.setIcon(QIcon(".\music\MusicIcon\MusicIcon.jpg"))
self.MusicIconLabel.setIconSize(QSize(30, 30))
else:
self.MusicIconLabel.setText("无法提取音频图片")
self.MusicIconLabel.setGeometry(20, 20, 120, 30)
self.MusicNameLabel = QLabel(self)
self.MusicNameLabel.setGeometry(20, int((self.height() - 30) / 2), 250, 30)
self.MusicNameLabel.setStyleSheet("font-size:10px;")
self.MusicNameLabel.setText(os.path.split(self.file)[-1])
self.volume = QSlider(Qt.Horizontal, self)
self.volume.setMinimum(0)
self.volume.setMaximum(100)
self.volume.setValue(50)
self.volume.setTickInterval(5)
self.volume.setTickPosition(QSlider.TicksBelow)
self.volume.setGeometry(10, 100, 150, 30)
self.volume.valueChanged.connect(self.VolumeNumber)
self.VolumeNumberLabel = QLabel(f"{self.volume.value()}", self)
self.VolumeNumberLabel.setGeometry(175, 100, 20, 20)
self.PlayButton = QPushButton(self)
self.PlayButton.setIcon(QIcon(".\image\stop.png"))
self.PlayButton.setIconSize(QSize(200, 200))
self.PlayButton.setGeometry(200, 100, 30, 30)
self.IS_PlayMusic = False
self.PlayButton.clicked.connect(self.PlayButtonEvent)
# 圆角
rect = QRectF(0, 0, self.width(), self.height())
path = QPainterPath()
path.addRoundedRect(rect, 10, 10)
polygon = path.toFillPolygon().toPolygon()
region = QRegion(polygon)
self.setMask(region)
def SetWindowMin(self):
self.setWindowState(Qt.WindowMinimized)
def QuitButtonEvent(self):
self.hide()
if os.path.isfile(".\music\MusicIcon\MusicIcon.jpg"):
os.remove(".\music\MusicIcon\MusicIcon.jpg")
self.player.stop()
def PlayButtonEvent(self):
if self.IS_PlayMusic:
self.PauseMusic()
else:
self.PlayMusic()
def VolumeNumber(self):
self.VolumeNumberLabel.setText(f"{self.volume.value()}")
self.player.setVolume(self.volume.value())
def GetMusicIcon(self):
self.MusicMutagnFile = File(self.file)
try:
self.MusicIconData = self.MusicMutagnFile.tags['APIC:test'].data
with open(".\music\MusicIcon\MusicIcon.jpg", "wb") as wfp:
wfp.write(self.MusicIconData)
except KeyError:
pass
def PlayMusic(self):
self.player.play()
self.PlayButton.setIcon(QIcon(".\image\play.png"))
self.PlayButton.setIconSize(QSize(200, 200))
self.IS_PlayMusic = True
def PauseMusic(self):
self.player.pause()
self.PlayButton.setIcon(QIcon(".\image\stop.png"))
self.PlayButton.setIconSize(QSize(200, 200))
self.IS_PlayMusic = False
"""重写移动事假,更改鼠标图标"""
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_flag = True
self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_flag:
self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
QMouseEvent.accept()
def mouseReleaseEvent(self, QMouseEvent):
self.m_flag = False
self.setCursor(QCursor(Qt.ArrowCursor))
WeatherGui.py
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QCursor
from PyQt5.QtGui import QRegion
from PyQt5.QtGui import QPainterPath
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QSize
from PyQt5.QtCore import QRectF
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QPushButton
import requests
"""天气查询界面"""
class WeatherGUI(QWidget):
def __init__(self):
super(WeatherGUI, self).__init__()
self.setWindowTitle("DesktopWife-WeatherGui")
self.resize(470, 270)
# 圆角
rect = QRectF(0, 0, self.width(), self.height())
path = QPainterPath()
path.addRoundedRect(rect, 10, 10)
polygon = path.toFillPolygon().toPolygon()
region = QRegion(polygon)
self.setMask(region)
self.QuitButton = QPushButton(self)
self.QuitButton.setIcon(QIcon(".\image\Quit.png"))
self.QuitButton.setIconSize(QSize(40, 40))
self.QuitButton.setGeometry(400, 10, 40, 40)
QuitButtonRect = QRectF(0, 0, self.QuitButton.width(), self.QuitButton.height())
QuitButtonPath = QPainterPath()
QuitButtonPath.addRoundedRect(QuitButtonRect, 50, 50)
QuitButtonPolygon = QuitButtonPath.toFillPolygon().toPolygon()
QuitButtonRegin = QRegion(QuitButtonPolygon)
self.QuitButton.setMask(QuitButtonRegin)
self.QuitButton.clicked.connect(self.hide)
self.WeatherText = QLabel(self)
self.WeatherText.setGeometry(int((470 - 300) / 2), int((270 - 200) / 2), 300, 200)
self.GetWeather()
def GetWeather(self):
GET = requests.get
if GET.status_code == 200:
JSON = GET.json()
INFO = JSON['info']
Data = f"城市:{JSON['city']}\n时间:{INFO['date']}" \
+ f"\n星期:{INFO['week']}\n天气:{INFO['type']}" \
+ f"\n{INFO['high']}\n{INFO['low']}\n风向:{INFO['fengxiang']}" \
+ f"\n风级:{INFO['fengli']}\n主人您要:{INFO['tip']}"
self.WeatherText.setText(Data)
else:
return False
"""重写移动事假,更改鼠标图标"""
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.m_flag = True
self.m_Position = event.globalPos() - self.pos() # 获取鼠标相对窗口的位置
event.accept()
self.setCursor(QCursor(Qt.OpenHandCursor)) # 更改鼠标图标
def mouseMoveEvent(self, QMouseEvent):
if Qt.LeftButton and self.m_flag:
self.move(QMouseEvent.globalPos() - self.m_Position) # 更改窗口位置
QMouseEvent.accept()
def mouseReleaseEvent(self, QMouseEvent):
self.m_flag = False
self.setCursor(QCursor(Qt.ArrowCursor))
语音
import os
import wave
import pyaudio
import speech_recognition
import speech_recognition as sr
from threading import Thread
import requests
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
_conent = True
def record_and_recog(wave_out_path, TIME=3):
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
wf = wave.open(wave_out_path, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
for _ in range(0, int(RATE / CHUNK * TIME)):
data = stream.read(CHUNK)
wf.writeframes(data)
stream.stop_stream()
stream.close()
p.terminate()
wf.close()
return wave_out_path
def TTS(Test: str):
GET = requests.get(f"https://tts.youdao.com/fanyivoice?word={Test}&le=zh&keyfrom=speaker-target")
if GET.status_code == 200:
with open(".\\out.mp3", "wb") as wfp:
wfp.write(GET.content)
wfp.close()
FFplay = os.popen(f"cd {os.path.split(__file__)[0]} && ffplay out.mp3 -noborder -nodisp -autoexit")
FFplay.readlines()
return True
else:
return False
def Scanning(Path="C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\"):
_DIRList = []
_File = []
for paths, dirs, files in os.walk(Path):
if dirs:
for dir in dirs:
_DIRList.append(paths+"\\"+dir)
if files:
for file in files:
_File.append(paths+"\\"+file)
return _File
def GoogleTranslate():
global _conent
while _conent:
Rec = sr.Recognizer()
with sr.AudioFile(record_and_recog(".\\test.wav")) as source:
audio = Rec.record(source)
try:
GoogleTranslateText = Rec.recognize_google(audio, language="zh-CN")
except speech_recognition.UnknownValueError:
continue
print(GoogleTranslateText)
if "小雨" in GoogleTranslateText or "小宇" in GoogleTranslateText:
TTS("主人我在听,请您下达命令")
NewRec = sr.Recognizer()
with sr.AudioFile(record_and_recog(".\\test.wav")) as Newsource:
NewAudio = NewRec.record(Newsource)
try:
Text = Rec.recognize_google(NewAudio, language="zh-CN")
except speech_recognition.UnknownValueError:
continue
print(Text)
elif "打开命令行" in Text:
TTS("好的, 主人")
os.popen(f"start cmd")
TTS("已为您打开命令行")
elif "关闭语音功能" in Text or "关闭语音" in Text:
TTS("好的,主人 下次再见")
break
elif "打开" in Text:
TTS("好的, 主人")
ISSTART = False
for _Path in Scanning():
if Text.strip("打开") == os.path.split(_Path)[-1].split(".")[0]:
os.popen(f'"{_Path}"')
print(_Path)
TTS(f"已为您打开 {Text.strip('打开')}")
ISSTART = True
break
if ISSTART:
continue
else:
TTS(f"主人未找到 {Text.strip('打开')}")
elif "关机" in Text:
TTS("主人是否确定要关机呢?")
shotdownRrc = sr.Recognizer()
with sr.AudioFile(record_and_recog(".\\out.mp3")) as shotdowndata:
shotdownAudio = shotdownRrc.record(shotdowndata)
try:
ISSHOTDOWN = Rec.recognize_google(shotdownAudio, language="zh-CN")
except speech_recognition.UnknownValueError:
continue
if ISSHOTDOWN in ["是", "是的", "没错", "要"]:
TTS("好的, 主人好好学习呀!")
os.popen("shutdown -s -t 1")
elif ISSHOTDOWN in ["否", "不", "不要", "不关机"]:
TTS("好的, 不进行关机")
else:
TTS("主人,我没听懂")
else
if GET.status_code == 200:
try:
TTS(str(GET.json()['data']['info']['text']).replace("小思", "小雨"))
except TypeError:
continue
def run():
Start = Thread(target=GoogleTranslate)
Start.start()
# Start.join()
使用 Python 实现一个可以语音交流的桌面宠物