197 lines
6.5 KiB
Python
197 lines
6.5 KiB
Python
import os
|
||
import tkinter as tk
|
||
from tkinter import messagebox, ttk
|
||
import sqlite3
|
||
import pygame
|
||
import subprocess
|
||
import pyaudio
|
||
import sys
|
||
import threading
|
||
import queue
|
||
import main
|
||
import app
|
||
# 在这里调用 main.py 中的函数或类
|
||
|
||
|
||
def get_match_logs(db_name="conversation.db"):
|
||
conn = sqlite3.connect(db_name)
|
||
c = conn.cursor()
|
||
c.execute("SELECT id, question, answer, audio_path FROM conversation")
|
||
logs = c.fetchall()
|
||
conn.close()
|
||
return logs
|
||
|
||
def delete_log(log_id, audio_path, db_name="conversation.db"):
|
||
conn = sqlite3.connect(db_name)
|
||
c = conn.cursor()
|
||
c.execute("DELETE FROM conversation WHERE id = ?", (log_id,))
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
# 删除音频文件
|
||
if audio_path and os.path.isfile(audio_path):
|
||
os.remove(audio_path)
|
||
|
||
def clear_all_logs(db_name="conversation.db"):
|
||
conn = sqlite3.connect(db_name)
|
||
c = conn.cursor()
|
||
c.execute("SELECT audio_path FROM conversation")
|
||
audio_paths = c.fetchall()
|
||
|
||
# 删除所有记录
|
||
c.execute("DELETE FROM conversation")
|
||
conn.commit()
|
||
conn.close()
|
||
|
||
# 删除所有音频文件
|
||
for path in audio_paths:
|
||
if path[0] and os.path.isfile(path[0]):
|
||
os.remove(path[0])
|
||
|
||
class App:
|
||
def __init__(self, root):
|
||
self.root = root
|
||
self.root.title("交流记录")
|
||
|
||
# 初始化pygame
|
||
pygame.mixer.init()
|
||
|
||
# 创建表格
|
||
self.tree = ttk.Treeview(root, columns=("Question", "Answer", "Audio Path"), show='headings')
|
||
self.tree.heading("Question", text="问题")
|
||
self.tree.heading("Answer", text="回答")
|
||
self.tree.heading("Audio Path", text="音频路径")
|
||
self.tree.pack(fill=tk.BOTH, expand=True)
|
||
|
||
# 添加滚动条
|
||
scrollbar = ttk.Scrollbar(root, orient=tk.VERTICAL, command=self.tree.yview)
|
||
self.tree.configure(yscroll=scrollbar.set)
|
||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||
|
||
# 加载日志
|
||
self.load_logs()
|
||
|
||
# 创建按钮容器
|
||
button_frame = tk.Frame(root)
|
||
button_frame.pack(pady=10)
|
||
|
||
# 删除按钮
|
||
self.delete_button = tk.Button(button_frame, text="删除选中记录", command=self.delete_selected)
|
||
self.delete_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 播放按钮
|
||
self.play_button = tk.Button(button_frame, text="播放音频", command=self.play_audio)
|
||
self.play_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 清除所有记录按钮
|
||
self.clear_button = tk.Button(button_frame, text="清除所有记录", command=self.clear_all)
|
||
self.clear_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 刷新记录按钮
|
||
self.refresh_button = tk.Button(button_frame, text="刷新记录", command=self.load_logs)
|
||
self.refresh_button.pack(side=tk.LEFT, padx=5)
|
||
|
||
# 添加执行主程序的按钮
|
||
self.start_button = tk.Button(root, text="开始录音和识别", command=self.start_main)
|
||
self.start_button.pack(pady=20)
|
||
|
||
# 创建小屏幕区域
|
||
full_width = self.root.winfo_width()
|
||
self.small_frame = tk.Frame(root, width=full_width, height=200, bg="black")
|
||
self.small_frame.pack(side=tk.RIGHT, padx=10, pady=10)
|
||
|
||
self.output_text = tk.Text(self.small_frame, bg="black", fg="white", wrap="word")
|
||
self.output_text.pack(expand=True, fill=tk.BOTH)
|
||
|
||
self.process = None
|
||
self.output_queue = queue.Queue() # 用于存放输出的队列
|
||
|
||
# 定时器检查队列中的输出
|
||
self.root.after(100, self.check_queue)
|
||
|
||
def start_main(self):
|
||
# 创建并启动线程
|
||
thread = threading.Thread(target=self.run_main)
|
||
thread.start()
|
||
|
||
def run_main(self):
|
||
# 获取当前脚本的路径
|
||
script_path = os.path.join(os.path.dirname(__file__), 'main.py')
|
||
|
||
# 调用 main.py,确保使用当前虚拟环境的 Python 解释器
|
||
self.process = subprocess.Popen(
|
||
[sys.executable, script_path],
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
text=True,
|
||
encoding='utf-8' # 设置编码为 utf-8
|
||
)
|
||
|
||
self.read_output()
|
||
|
||
def read_output(self):
|
||
if self.process:
|
||
output = self.process.stdout.readline()
|
||
if output:
|
||
self.output_queue.put(output) # 将输出放入队列
|
||
if self.process.poll() is None: # 进程仍在运行
|
||
self.root.after(100, self.read_output)
|
||
|
||
def check_queue(self):
|
||
while not self.output_queue.empty():
|
||
output = self.output_queue.get()
|
||
self.output_text.insert(tk.END, output)
|
||
self.output_text.see(tk.END) # 自动滚动到最新输出
|
||
self.root.after(100, self.check_queue) # 定时检查队列
|
||
|
||
def load_logs(self):
|
||
for row in self.tree.get_children():
|
||
self.tree.delete(row)
|
||
logs = get_match_logs()
|
||
for log in logs:
|
||
self.tree.insert("", tk.END, values=(log[1], log[2], log[3]))
|
||
|
||
def delete_selected(self):
|
||
selected_item = self.tree.selection()
|
||
if selected_item:
|
||
selected_index = self.tree.index(selected_item[0])
|
||
log_id = get_match_logs()[selected_index][0]
|
||
audio_path = get_match_logs()[selected_index][3]
|
||
full_audio_path = os.path.join("static", audio_path)
|
||
delete_log(log_id, full_audio_path)
|
||
self.load_logs()
|
||
else:
|
||
messagebox.showwarning("警告", "请先选择要删除的记录。")
|
||
|
||
def play_audio(self):
|
||
selected_item = self.tree.selection()
|
||
if selected_item:
|
||
selected_index = self.tree.index(selected_item[0])
|
||
audio_path = get_match_logs()[selected_index][3]
|
||
|
||
# 拼接静态文件夹路径
|
||
full_audio_path = os.path.join("static", audio_path)
|
||
|
||
# 打印音频路径用于调试
|
||
print("尝试加载音频文件:", full_audio_path)
|
||
|
||
# 检查文件是否存在
|
||
if os.path.isfile(full_audio_path):
|
||
pygame.mixer.music.load(full_audio_path)
|
||
pygame.mixer.music.play()
|
||
else:
|
||
messagebox.showerror("错误", "音频文件不存在。")
|
||
else:
|
||
messagebox.showwarning("警告", "请先选择要播放的记录。")
|
||
|
||
def clear_all(self):
|
||
confirm = messagebox.askyesno("确认", "您确定要清除所有记录吗?")
|
||
if confirm:
|
||
clear_all_logs()
|
||
self.load_logs()
|
||
|
||
if __name__ == '__main__':
|
||
root = tk.Tk()
|
||
app = App(root)
|
||
root.mainloop()
|