这串代码比较长,但是出问题的只是其中的一段,也就是open_Windows3这个函数
import tkinter as tk
import sqlite3
import os
import socket
import threading
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import time
#last_a = ''
#send_flag = False
#fig = None
#client_socket = None
class App:
def __init__(self, master):
self.master = master
self.send_flag = False
self.last_a = ''
self.fig = None
self.client_socket = None
self.open_window_button = tk.Button(master, text="聊天记录", command=self.open_window)
self.open_window_button.pack()
self.open_window_button = tk.Button(master, text="聊天界面", command=self.open_window2)
self.open_window_button.pack()
self.open_window_button = tk.Button(master, text="函数图形", command=self.open_window3)
self.open_window_button.pack()
def open_window(self):
# 创建连接和游标对象
DB_FILE = "chat2.db"
conn = sqlite3.connect(DB_FILE)
c = conn.cursor()
# 创建一个GUI窗口
search_window = tk.Toplevel(self.master)
search_window.title("Chat Database")
search_window.geometry("1000x500")
# 定义显示全部消息的函数
def show_all_messages():
# 执行SELECT命令
c.execute('SELECT * FROM messages')
results = c.fetchall()
# 清空text框
text.delete("1.0", tk.END)
# 在text框中显示消息记录
for row in results:
text.insert(tk.END, f"ID: {row[0]}\n")
text.insert(tk.END, f"Sender: {row[1]}\n")
text.insert(tk.END, f"Receiver: {row[2]}\n")
text.insert(tk.END, f"Message: {row[3]}\n")
text.insert(tk.END, f"Time: {row[4]}\n\n")
# 定义按关键字查找消息的函数
def search_by_keyword(keyword):
# 使用LIKE操作符进行模糊匹配
c.execute("SELECT * FROM messages WHERE message LIKE ?", ('%'+keyword+'%',))
results = c.fetchall()
# 清空text框
text.delete("1.0", tk.END)
# 在text框中显示搜索结果
for row in results:
text.insert(tk.END, f"ID: {row[0]}\n")
text.insert(tk.END, f"Sender: {row[1]}\n")
text.insert(tk.END, f"Receiver: {row[2]}\n")
text.insert(tk.END, f"Message: {row[3]}\n")
text.insert(tk.END, f"Time: {row[4]}\n\n")
# 定义按时间查找消息的函数
def search_by_time(start_date, end_date):
# 构造时间字符串
start_time = start_date + " 00:00:00"
end_time = end_date + " 23:59:59"
# 执行SELECT命令
c.execute("SELECT * FROM messages WHERE timestamp BETWEEN ? AND ?", (start_time, end_time))
results = c.fetchall()
# 清空text框
text.delete("1.0", tk.END)
# 在text框中显示搜索结果
for row in results:
text.insert(tk.END, f"ID: {row[0]}\n")
text.insert(tk.END, f"Sender: {row[1]}\n")
text.insert(tk.END, f"Receiver: {row[2]}\n")
text.insert(tk.END, f"Message: {row[3]}\n")
text.insert(tk.END, f"Time: {row[4]}\n\n")
# 定义显示搜索窗口的函数
def show_search_window():
# 创建新窗口
search_window = tk.Toplevel(self.master)
search_window.title("Search Messages")
# 添加按关键字搜索的部分
keyword_label = tk.Label(search_window, text="Keyword:")
keyword_label.pack()
keyword_entry = tk.Entry(search_window)
keyword_entry.pack()
keyword_button = tk.Button(search_window, text="Search by Keyword",
command=lambda: search_by_keyword(keyword_entry.get()))
keyword_button.pack()
# 添加按时间搜索的部分
time_label1 = tk.Label(search_window, text="Start Date (yyyy-mm-dd):")
time_label1.pack()
time_entry1 = tk.Entry(search_window)
time_entry1.pack()
time_label2 = tk.Label(search_window, text="End Date (yyyy-mm-dd):")
time_label2.pack()
time_entry2 = tk.Entry(search_window)
time_entry2.pack()
time_button = tk.Button(search_window, text="Search by Time",
command=lambda: search_by_time(time_entry1.get(), time_entry2.get()))
time_button.pack()
# 定义删除消息的函数
def delete_message():
message_id = delete_entry.get()
if not message_id:
# 如果用户未输入任何内容,清空文本框并返回
delete_entry.delete(0, 'end')
return
try:
message_id = int(message_id)
except ValueError:
# 如果用户输入的值无法转换为整数,弹出错误提示框并返回
messagebox.showerror('Error', 'Invalid message ID')
delete_entry.delete(0, 'end')
return
# 删除消息记录
c.execute("DELETE FROM messages WHERE id=?", (message_id,))
conn.commit()
# 在text框中显示删除成功提示
text.delete("1.0", tk.END)
text.insert(tk.END, f"Message with ID {message_id} deleted successfully.")
# 添加按钮和text控件
show_all_button = tk.Button(search_window, text="Show all messages", command=show_all_messages, width=20, height=2)
show_all_button.place(x=700, y=20)
search_button = tk.Button(search_window, text="Search messages", command=show_search_window, width=20, height=2)
search_button.place(x=700, y=80)
delete_label = tk.Label(search_window, text="Message ID to delete:")
delete_label.place(x=700, y=140)
delete_entry = tk.Entry(search_window, width=20)
delete_entry.place(x=700, y=170)
delete_button = tk.Button(search_window, text="Delete", command=delete_message, width=20, height=2)
delete_button.place(x=700, y=210)
text = tk.Text(search_window, width=60, height=30)
text.place(x=20, y=20)
def open_window2(self):
# 查询 messages 表是否已经存在,不存在则创建
conn = sqlite3.connect('chat2.db')
c = conn.cursor()
c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='messages'")
result = c.fetchone()
if result is None:
c.execute('''CREATE TABLE messages (id INTEGER PRIMARY KEY AUTOINCREMENT, sender TEXT, receiver TEXT, message TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
conn.commit()
conn.close()
# 发送消息到服务端
def send(clientsocket):
# 建立数据库连接和游标对象
with sqlite3.connect('chat2.db') as conn_send:
c_send = conn_send.cursor()
while True:
data = input_box.get()
if not data:
print('Closing connection')
break
# 发送消息给服务端
clientsocket.send(data.encode())
# 将消息保存到数据库中
sender = 'Client'
receiver = 'Server'
message = data
c_send.execute("INSERT INTO messages (sender, receiver, message) VALUES (?, ?, ?)", (sender, receiver, message))
conn_send.commit()
message_box.config(state=tk.NORMAL)
message_box.insert(tk.END, f"{sender}: {message}\n")
message_box.config(state=tk.DISABLED)
input_box.delete(0, tk.END)
def receive_thread():
# 初始化消息框内容
# 查询数据库中的历史消息,并显示在消息显示区域中
conn = sqlite3.connect('chat2.db')
c = conn.cursor()
c.execute('''SELECT sender, message FROM messages ORDER BY id DESC LIMIT 20''')
rows = c.fetchall()
rows.reverse()
message_box.config(state=tk.NORMAL)
for row in rows:
message_box.insert(tk.END, f"{row[0]}: {row[1]}\n")
message_box.config(state=tk.DISABLED)
conn.close()
message_box.config(state=tk.NORMAL)
message_box.insert(tk.END, "等待消息...\n")
message_box.config(state=tk.DISABLED)
# 循环接收消息
while True:
try:
# 接收数据
data = clientsocket.recv(1024)
except ConnectionResetError:
print("连接已断开")
clientsocket.close()
break
except ConnectionAbortedError:
print("连接已中止")
clientsocket.close()
break
if not data:
print('Client disconnected')
break
# 显示接收到的消息并保存到数据库中
message = data.decode()
print('Received from server:', message)
# 在消息框中显示消息
message_box.config(state=tk.NORMAL)
message_box.insert(tk.END, f"Sever: {message}\n")
message_box.config(state=tk.DISABLED)
# 将消息保存到数据库中
conn_recv = sqlite3.connect('chat2.db')
c_recv = conn_recv.cursor()
sender = 'Client'
receiver = 'Server'
c_recv.execute("INSERT INTO messages (sender, receiver, message) VALUES (?, ?, ?)", (sender, receiver, message))
conn_recv.commit()
conn_recv.close()
# 关闭连接
try:
if input_box.winfo_exists():
input_box.config(state=tk.DISABLED)
except tk.TclError:
pass
try:
if send_button.winfo_exists():
send_button.config(state=tk.DISABLED)
except tk.TclError:
pass
clientsocket.close()
def start_send_thread():
threading.Thread(target=send, args=(clientsocket,)).start()
# 创建图形界面
root = tk.Tk()
root.title("Chat Client")
# 输入消息
input_label = tk.Label(root, text="Message:")
input_label.pack(side=tk.LEFT)
input_box = tk.Entry(root)
input_box.pack(side=tk.LEFT)
# 发送按钮
send_button = tk.Button(root, text='Send', font=('Arial', 12), width=5, command=start_send_thread)
send_button.pack(side=tk.LEFT)
# 消息显示区域
message_scrollbar = tk.Scrollbar(root)
message_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
message_box = tk.Text(root, state=tk.DISABLED)
message_box.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
message_scrollbar.config(command=message_box.yview)
message_box.config(yscrollcommand=message_scrollbar.set)
# 创建 socket 对象并连接服务器
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
clientsocket.connect(('127.0.0.1',8000))
print('Connected to server')
# 启动发送和接收线程
send_thread = threading.Thread(target=send, args=(clientsocket,))
receive_thread = threading.Thread(target=receive_thread)
send_thread.start()
receive_thread.start()
# 关闭连接和数据库连接
root.protocol("WM_DELETE_WINDOW", lambda: [clientsocket.close(), conn.close(), root.destroy()])
root.mainloop()
# 等待发送和接收线程结束
send_thread.join()
receive_thread.join()
def close_db(self):
self.conn.close()
self.clientsocket.close()
self.serversocket.close()
def open_window3(self):
def send():
while True:
if self.send_flag:
a = fn_entry.get()
if a != self.last_a:
self.client_socket.send(a.encode())
self.last_a = a
self.send_flag = False
time.sleep(0.1)
def start_send_thread():
threading.Thread(target=send).start()
def receive_and_draw_graph():
while True:
try:
a = self.client_socket.recv(1024).decode('utf-8')
if not a:
self.client_socket.close()
break
root.after(100, lambda: draw_graph(a))
except ConnectionResetError:
self.client_socket.close()
break
except ConnectionAbortedError:
print("服务器已关闭连接!")
self.client_socket.close()
break
def draw_graph(a=None):
if a is None:
a = fn_entry.get()
x = np.linspace(-10, 10, 1000)
try:
y = eval(str(a))
except:
error_label.config(text="输入函数有误!!!")
return
if self.fig is None:
self.fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 8))
self.fig.canvas.set_window_title("函数图像")
ax1.plot(x, y, label="f(x)", color='red')
ax1.set_xlabel("X")
ax1.set_ylabel("Y")
ax1.legend()
plot_derivative(a, ax2)
ax2.set_xlabel("X")
ax2.set_ylabel("Y")
ax2.legend()
canvas = FigureCanvasTkAgg(self.fig, master=root)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.fig.canvas.draw_idle()
else:
ax1, ax2 = self.fig.get_axes()
ax1.lines[0].set_data(x, y)
plot_derivative(a, ax2)
self.fig.canvas.draw_idle()
def plot_derivative(f, ax, x_range=(-10, 10)):
x = np.linspace(x_range[0], x_range[1], 1000)
try:
dy = np.gradient(eval(f), x)
ax.clear()
ax.plot(x, dy, linewidth=1, color='pink', label="f'(x)")
ax.legend()
except:
error_label.config(text="无法绘制导函数图像!!!")
root = tk.Tk()
root.title("函数图像")
input_frame = tk.Frame(root)
input_frame.pack()
fn_label = tk.Label(input_frame, text="函数:")
fn_label.pack(side=tk.LEFT)
fn_entry = tk.Entry(input_frame)
fn_entry.pack(side=tk.LEFT)
error_label = tk.Label(root, fg="red")
error_label.pack()
button = tk.Button(root, text="确定", command=lambda: [draw_graph(), send_data()])
button.pack()
def send_data():
self.send_flag = True
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
clientsocket.connect(('127.0.0.1',8001))
print('Connected to server')
self.client_socket = clientsocket
start_send_thread()
receive_thread = threading.Thread(target=receive_and_draw_graph)
receive_thread.start()
root.protocol("WM_DELETE_WINDOW", lambda: [self.client_socket.close(), root.destroy()])
root.mainloop()
receive_thread.join()
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
root.mainloop()
这段代码在我运行后点击函数图形后会出现两个问题,第一个是输入函数方程后点击确认,所有的图形化界面会缩小;第二个问题是,在启用函数图像这个功能并关闭后,再关闭主界面后,程序运行并不会暂停,而是持续运行,然后就是如果不点函数图像这个功能然后关闭所有界面,程序可以正常结束运行,这两个问题该如何解决。
哼,能有多长
~~~~打扰了