目录
简介
程序
源代码
GUI
DesktopWife.py
MusicPlayer.py
WeatherGui.py
语音
简介
普通的桌面宠物程序只能动一动,于是我给程序添加了语言,既可以聊天,也可以实现一些自动功能,不如搜索,打开程序什么的。
程序
源代码
gui界面都是使用PyQt5开发的,语音唤醒功能也是使用的第三方库和api
GUI
DesktopWife.py
import sys
import osfrom 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 QMessageBoximport requestsimport WeatherGui
import MusicPlayer
import Tray
import VoiceToTextVoiceToText.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 = Falseself.close()sys.exit()"""系统托盘"""def SetTray(self):self._Tray = Tray.TrayIcon(self)self._Tray.show()self.hide()"""随机一诗"""# 因为csdn的智障检测,这里无法查看"""音乐播放"""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 = Trueself.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 = Falseself.setCursor(QCursor(Qt.ArrowCursor))if __name__ == '__main__':app = QApplication(sys.argv)Window = DesktopWife()Window.show()app.exec_()
MusicPlayer.py
import osfrom 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 QPushButtonfrom mutagen import File"""音乐播放界面"""
class MusicGui(QWidget):def __init__(self, _file):super(MusicGui, self).__init__()self.file = _fileself.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 = Falseself.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'].datawith open(".\music\MusicIcon\MusicIcon.jpg", "wb") as wfp:wfp.write(self.MusicIconData)except KeyError:passdef PlayMusic(self):self.player.play()self.PlayButton.setIcon(QIcon(".\image\play.png"))self.PlayButton.setIconSize(QSize(200, 200))self.IS_PlayMusic = Truedef 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 = Trueself.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 = Falseself.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 QPushButtonimport 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("# 因为csdn的智障检测,这里无法查看")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 = Trueself.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 = Falseself.setCursor(QCursor(Qt.ArrowCursor))
语音
import os
import wave
import pyaudio
import speech_recognition
import speech_recognition as sr
from threading import Thread
import requestsCHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000_conent = Truedef 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_pathdef 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 Trueelse:return Falsedef 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 _Filedef GoogleTranslate():global _conentwhile _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:continueprint(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:continueprint(Text)# 因为csdn智障检测,这里无法查看elif "打开命令行" in Text:TTS("好的, 主人")os.popen(f"start cmd")TTS("已为您打开命令行")elif "关闭语音功能" in Text or "关闭语音" in Text:TTS("好的,主人 下次再见")breakelif "打开" in Text:TTS("好的, 主人")ISSTART = Falsefor _Path in Scanning():if Text.strip("打开") == os.path.split(_Path)[-1].split(".")[0]:os.popen(f'"{_Path}"')print(_Path)TTS(f"已为您打开 {Text.strip('打开')}")ISSTART = Truebreakif ISSTART:continueelse: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:continueif ISSHOTDOWN in ["是", "是的", "没错", "要"]:TTS("好的, 主人好好学习呀!")os.popen("shutdown -s -t 1")elif ISSHOTDOWN in ["否", "不", "不要", "不关机"]:TTS("好的, 不进行关机")else:TTS("主人,我没听懂")else:
# 因为csdn的智障检测,这里无法查看if GET.status_code == 200:try:TTS(str(GET.json()['data']['info']['text']).replace("小思", "小雨"))except TypeError:continuedef run():Start = Thread(target=GoogleTranslate)Start.start()# Start.join()
使用 Python 实现一个可以语音交流的桌面宠物