PySimpleGUI 综合应用
目录
应用界面
完整代码
英语朗读器.pyw
import PySimpleGUI as sg
import pyttsx3,pyaudio,pyperclip
import os,re,datetime,wave,threading
from rapidfuzz import fuzz
class AudioPlayer(threading.Thread):
def __init__(self, filename):
super().__init__()
self.filename = filename
self.st, self.pa, self.wf = None, None, None
self.stop_event = threading.Event()
def run(self):
self.wf = wave.open(self.filename, 'rb')
self.pa = pyaudio.PyAudio()
self.st = self.pa.open(format=self.pa.get_format_from_width(self.wf.getsampwidth()),
channels=self.wf.getnchannels(), rate=self.wf.getframerate(), output=True)
data = self.wf.readframes(1024)
while not self.stop_event.is_set() and len(data) > 0:
self.stop_event.wait(0.01) # 检查停止事件(非阻塞)
if not self.stop_event.is_set():
self.st.write(data)
data = self.wf.readframes(1024)
if self.st:
self.st.stop_stream()
self.st.close()
if self.pa:
self.pa.terminate()
def stop(self):
self.stop_event.set() # 设置停止标志
def loadSentence(file):
res = [],[]
try:
with open('en'+file+'.txt','r',encoding='utf-8') as f:
text = f.readlines()
for txt in text:
if txt.count('|')!=1: continue
if txt.endswith('\n'): txt=txt[:-1]
for i,t in enumerate(txt.split('|')):
res[i].append(t)
return res
except:
sg.popup_error(f'文件[{file}]不存在,程序无法运行!', font=txFont, title='Error')
return None,
def engineSay(txt):
engine.say(txt)
engine.runAndWait()
def engineFile(txt, mp3File):
try:
if os.path.exists(mp3File):
os.remove(mp3File)
widgetDisabled(['朗读列表'])
showMessage('语音文件生成中,请稍候......')
audio = engine.save_to_file(txt, mp3File)
engine.runAndWait()
showMessage('朗读中......')
widgetDisabled(['停止播放'], False)
window.Refresh()
return True
except:
sg.popup_error('生成语音文件失败,无法朗读!', font=txFont, title='Error')
return False
def stringSize(s):
return len(s)+len([c for c in s if '\u4e00'<=c<='\u9fff'])+1
def deleteAllMp3():
count = 0
for file in os.listdir('.'):
if (os.path.isfile(file) and 'Voice' in file and 'Speed' in file
and file.startswith('en') and file.endswith('.mp3')):
try:
count += 1
os.remove(file)
except: pass
if count:
msg = f'已删除{count}个临时语音文件。'
else:
msg = f'当前没有临时语音文件,或者删除文件失败。'
showMessage(msg)
def showMessage(msg='', widget='-STATUS-'):
window[widget].update(msg)
window.Refresh()
def widgetDisabled(widgets,disabled=True):
for w in widgets:
window[w].Update(disabled=disabled)
window.Refresh()
def listUpdate(value):
window["-LIST-"].update(values=value)
window.Refresh()
def setFocus():
window['-TARGET-'].widget.select_from(0)
window['-TARGET-'].widget.select_to(len(values['-TARGET-']))
window['-TARGET-'].SetFocus(True)
def strDateTime():
now = datetime.datetime.now()
return f'({now.year:04}{now.month:02}{now.day:02}{now.hour:02}{now.minute:02})'
def fuzzMatch(target, percent):
if not target: return [[],[]]
Result = dict()
Search = re.compile(r'[\u4e00-\u9fa5]').search(target)
Source = inText[1] if Search else inText[0]
for s in Source:
for i in range(len(s)-len(target)+1):
if fuzz.ratio(s[i:i+len(target)].lower(), target.lower()) >= percent: