python ai回答界面promax版本

优化了一系列功能,背景,表情包,存储对话等等

import tkinter as tk  # 用于创建图形用户界面
from tkinter import ttk, filedialog, messagebox, colorchooser  # 导入 tkinter 的一些子模块
import threading  # 用于实现多线程
import time  # 用于处理时间相关的功能
import pyttsx3  # 用于将文本转换为语音
import speech_recognition as sr  # 用于语音识别
import requests  # 用于发送 HTTP 请求
import urllib.parse  # 用于解析 URL
import logging  # 用于记录日志
from PIL import Image, ImageTk  # 用于处理图像
import emoji  # 用于处理表情符号

# 设置基本日志配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class LoginWindow:
    def __init__(self, master):
        """初始化登录窗口"""
        self.master = master
        self.master.title("登录")  # 设置窗口标题
        self.master.geometry("300x150")  # 设置窗口大小
        self.create_widgets()

    def create_widgets(self):
        """创建登录窗口的组件"""
        tk.Label(self.master, text="账号:").grid(row=0, column=0, padx=10, pady=10)
        self.username_entry = tk.Entry(self.master)
        self.username_entry.grid(row=0, column=1, padx=10, pady=10)
        self.username_entry.bind("<Return>", self.check_login)

        tk.Label(self.master, text="密码:").grid(row=1, column=0, padx=10, pady=10)
        self.password_entry = tk.Entry(self.master, show="*")
        self.password_entry.grid(row=1, column=1, padx=10, pady=10)
        self.password_entry.bind("<Return>", self.check_login)

        tk.Button(self.master, text="登录", command=self.check_login).grid(row=2, column=0, columnspan=2, pady=10)

    def check_login(self, event=None):
        """检查登录账号和密码是否正确"""
        username = self.username_entry.get()
        password = self.password_entry.get()
        if username == "123" and password == "123":
            self.master.destroy()
            main()
        else:
            messagebox.showerror("错误", "账号或密码错误")

class SpeechApp:
    def __init__(self, master):
        """初始化语音聊天机器人窗口"""
        self.master = master
        self.master.title("语音聊天机器人")
        self.master.geometry("600x600")
        self.engine = pyttsx3.init()  # 初始化文本转语音引擎
        self.recognizer = sr.Recognizer()  # 初始化语音识别器
        self.listening = False  # 监听状态标志
        self.voice_type = "BV001_streaming"
        self.user_avatar = ImageTk.PhotoImage(Image.open("wo.jpg").resize((50, 50), Image.Resampling.LANCZOS))  # 用户头像
        self.bot_avatar = ImageTk.PhotoImage(Image.open("robot.png").resize((50, 50), Image.Resampling.LANCZOS))  # 机器人头像
        self.setup_ui()
        self.background_color = None
        self.dialog_background_color = None
        self.selected_emoji = None

    def setup_ui(self):
        """设置用户界面"""
        frame = tk.Frame(self.master, bg='white')
        frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)

        self.canvas = tk.Canvas(frame, bg='white')
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        self.scrollbar = ttk.Scrollbar(frame, command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        self.messages_frame = tk.Frame(self.canvas, bg='white')
        self.canvas.create_window((0, 0), window=self.messages_frame, anchor='nw')
        self.messages_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))

        entry_frame = tk.Frame(self.master)
        entry_frame.pack(fill=tk.X, padx=10, pady=10)
        self.text_entry = ttk.Entry(entry_frame, width=80)
        self.text_entry.bind("<Return>", self.on_text_entry)
        self.text_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        emoji_button = ttk.Button(entry_frame, text="选择表情", command=self.choose_emoji)
        emoji_button.pack(side=tk.LEFT)

        self.voice_combo = ttk.Combobox(self.master, state='readonly', values=['Male Voice', 'Female Voice'])
        self.voice_combo.set('Male Voice')
        self.voice_combo.pack(pady=5)
        self.voice_combo.bind("<<ComboboxSelected>>", self.on_voice_change)

        button_frame = tk.Frame(self.master)
        button_frame.pack(pady=10)
        self.speak_button = ttk.Button(button_frame, text="开始说话")
        self.speak_button.pack(side=tk.LEFT, padx=5)
        self.speak_button.bind("<ButtonPress>", self.on_speak_button_press)
        self.speak_button.bind("<ButtonRelease>", self.on_speak_button_release)
        ttk.Button(button_frame, text="更换界面背景", command=self.change_background_interface).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="更换对话框背景", command=self.change_background_dialog).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="保存对话", command=self.save_conversation).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="退出", command=self.on_close).pack(side=tk.LEFT, padx=5)
        self.master.protocol("WM_DELETE_WINDOW", self.on_close)

    def on_voice_change(self, event):
        """更改语音类型"""
        voice_label = self.voice_combo.get()
        if voice_label == 'Female Voice':
            self.voice_type = "BV001_streaming"
        elif voice_label == 'Male Voice':
            self.voice_type = "BV002_streaming"
        self.speak("Voice changed to " + voice_label)

    def on_speak_button_press(self, event):
        """开始监听语音输入"""
        self.listening = True
        threading.Thread(target=self.continuous_listen).start()

    def on_speak_button_release(self, event):
        """停止监听语音输入"""
        self.listening = False

    def continuous_listen(self):
        """连续监听语音输入并识别文本"""
        with sr.Microphone() as source:
            self.recognizer.adjust_for_ambient_noise(source)
            while self.listening:
                try:
                    print("Listening...")
                    audio = self.recognizer.listen(source, timeout=1, phrase_time_limit=5)
                    text = self.recognizer.recognize_google(audio, language='zh-CN')
                    print(f"Recognized: {text}")
                    if text:
                        self.update_conversation(text, "You")
                        response = self.chat_with_qingyunke(text)
                        self.update_conversation(response, "System")
                        self.speak(response)
                except sr.WaitTimeoutError:
                    print("Timeout, listening again...")
                except sr.UnknownValueError:
                    print("Could not understand audio")
                except sr.RequestError as e:
                    print(f"Could not request results; {e}")

    def chat_with_qingyunke(self, message):
        """与青云客 API 进行对话"""
        base_url = "http://api.qingyunke.com/api.php"
        params = {"key": "free", "appid": 0, "msg": urllib.parse.quote(message)}
        try:
            response = requests.get(base_url, params=params, timeout=10)
            response.raise_for_status()
            return response.json()['content'].replace('{br}', '\n')
        except requests.RequestException as e:
            logging.error("Network error: " + str(e))
            return "网络错误,请稍后再试"

    def on_text_entry(self, event):
        """处理文本输入并进行对话"""
        message = self.text_entry.get()
        if message or self.selected_emoji:
            self.text_entry.delete(0, tk.END)
            message_with_emoji = message + (self.selected_emoji if self.selected_emoji else "")
            self.update_conversation(message_with_emoji, "You")
            self.selected_emoji = None
            response = self.chat_with_qingyunke(message_with_emoji)
            self.update_conversation(response, "System")
            self.speak(response)

    def change_background_interface(self):
        """更改界面背景颜色"""
        color = colorchooser.askcolor(title="选择界面背景颜色")[1]
        if color:
            self.master.config(bg=color)
            self.canvas.config(bg=color)
            self.messages_frame.config(bg=color)
            self.background_color = color

    def change_background_dialog(self):
        """更改对话框背景颜色"""
        color = colorchooser.askcolor(title="选择对话框背景颜色")[1]
        if color:
            self.dialog_background_color = color

    def choose_emoji(self):
        """选择表情符号"""
        emoji_window = tk.Toplevel(self.master)
        emoji_window.title("选择表情")
        emoji_window.geometry("500x300")
        emoji_frame = tk.Frame(emoji_window)
        emoji_frame.pack(fill=tk.BOTH, expand=True)
        canvas = tk.Canvas(emoji_frame)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar = ttk.Scrollbar(emoji_frame, orient="vertical", command=canvas.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.configure(yscrollcommand=scrollbar.set)
        canvas.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
        emojis_frame = tk.Frame(canvas)
        canvas.create_window((0, 0), window=emojis_frame, anchor='nw')
        emojis = ['😀', '😂', '🤣', '🙃', '😍', '😁', '😅', '🤔', '😮', '😛', '😢', '😠']
        for emj in emojis:
            btn = ttk.Button(emojis_frame, text=emj, command=lambda e=emj: self.select_emoji(e, emoji_window))
            btn.pack(side=tk.LEFT, padx=5, pady=5)

    def select_emoji(self, emj, window):
        """选择具体表情符号并关闭选择窗口"""
        self.selected_emoji = emoji.emojize(emj)
        window.destroy()

    def speak(self, text):
        """将文本转换为语音"""
        self.txt_to_voice(text)

    def txt_to_voice(self, msg):
        """文本转语音"""
        engine = pyttsx3.init()
        engine.setProperty('rate', 150)
        engine.setProperty('volume', 1)
        voices = engine.getProperty('voices')
        if self.voice_type == "BV001_streaming":
            engine.setProperty('voice', voices[0].id)
        else:
            engine.setProperty('voice', voices[1].id)
        engine.say(msg)
        engine.runAndWait()
        engine.stop()

    def update_conversation(self, text, speaker):
        """更新对话框内容"""
        def update():
            time_stamp = time.strftime("%Y-%m-%d %H:%M:%S")
            if speaker == "You":
                avatar = self.user_avatar
                name = "You"
                side = 'right'
            else:
                avatar = self.bot_avatar
                name = "Robot"
                side = 'left'
            message_frame = tk.Frame(self.messages_frame, bg=self.background_color or 'white')
            message_frame.pack(fill=tk.X, pady=5, padx=10)
            if side == 'right':
                text_frame = tk.Frame(message_frame, bg=self.dialog_background_color or 'lightblue')
                text_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5)
                avatar_frame = tk.Frame(message_frame, bg=self.background_color or 'white')
                avatar_frame.pack(side=tk.RIGHT, padx=5)
                avatar_label = tk.Label(avatar_frame, image=avatar, bg=self.background_color or 'white')
                avatar_label.pack()
            else:
                avatar_frame = tk.Frame(message_frame, bg=self.background_color or 'white')
                avatar_frame.pack(side=tk.LEFT, padx=5)
                avatar_label = tk.Label(avatar_frame, image=avatar, bg=self.background_color or 'white')
                avatar_label.pack()
                text_frame = tk.Frame(message_frame, bg=self.dialog_background_color or 'pink')
                text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5)
            name_time_label = tk.Label(text_frame, text=f"{name} {time_stamp}",
                                       bg=self.dialog_background_color or 'white', font=("Arial", 8), anchor='w')
            name_time_label.pack(fill=tk.X)
            message_label = tk.Label(text_frame, text=text, bg=self.dialog_background_color or 'white', wraplength=400,
                                     justify='left')
            message_label.pack(padx=5, pady=5)
            self.canvas.update_idletasks()
            self.canvas.yview_moveto(1)
        self.messages_frame.after(0, update)

    def save_conversation(self):
        """保存对话内容"""
        messages = []
        for child in self.messages_frame.winfo_children():
            if isinstance(child, tk.Frame):
                for frame in child.winfo_children():
                    if isinstance(frame, tk.Frame):
                        for widget in frame.winfo_children():
                            if isinstance(widget, tk.Label):
                                messages.append(widget.cget("text"))
        file_path = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files", "*.txt")])
        if file_path:
            with open(file_path, 'w', encoding='utf-8') as file:
                for message in messages:
                    file.write(message + '\n')
            messagebox.showinfo("保存成功", "对话已成功保存")

    def on_close(self):
        """处理窗口关闭事件"""
        if messagebox.askokcancel("退出", "确定要退出吗?"):
            self.master.destroy()

def main():
    """创建并运行语音聊天机器人窗口"""
    root = tk.Tk()
    app = SpeechApp(root)
    root.mainloop()

if __name__ == "__main__":
    login_root = tk.Tk()
    login_app = LoginWindow(login_root)
    login_root.mainloop()

  • 24
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好运仅李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值