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()