# 服务端程序
import socket
import threading
from tkinter import *
from tkinter import messagebox
import matplotlib.pyplot as plt
import numpy as np
from math import *
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# 创建套接字并绑定地址
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), 1234))
s.listen(1)
clientsocket, clientaddress = s.accept()
send_flag = False
running = True
def receive_messages():
global running
while running:
try:
data = clientsocket.recv(1024).decode()
if data:
chat_message.configure(state=NORMAL)
chat_message.insert(END, "客户端:"+data + '\n')
chat_message.configure(state=DISABLED)
if data.startswith("Function:y="):
function_str=data[11:]
try:
x = np.linspace(-10, 10, 100) # 创建一个包含-10到10的100个数据点的数组
if "x" not in function_str:
raise ValueError("函数中未包含自变量 x")
y = eval(function_str) # 计算函数在x值上的y值
dy_dx = np.gradient(y, x) # 计算函数在x值上的一阶导数
# 绘制函数及其一阶导数的图像
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(x, y)
plt.title('Function')
plt.xlabel('x')
plt.ylabel('y')
plt.subplot(2, 1, 2)
plt.plot(x, dy_dx)
plt.title('First Derivative')
plt.xlabel('x')
plt.ylabel("dy/dx")
plt.tight_layout()
plt.show()
except Exception as e:
chat_message.insert(END, "计算出错:" + str(e) + '\n')
except ConnectionError:
break
# 将表达式转化为函数
def f(x, expression):
func = np.vectorize(lambda x: eval(expression))
return func(x)
# 求取函数的一阶导函数
def g(x, expression):
return np.gradient(f(x, expression), x)
def send_message():
global send_flag
if send_flag:
message = input_message.get("1.0", END).strip()
if message:
input_message.delete("1.0", END)
chat_message.configure(state=NORMAL)
chat_message.insert(END,"我:"+message + '\n')
chat_message.configure(state=DISABLED)
clientsocket.send(message.encode())
send_flag = False
def show_graph():
expression = input_message.get("1.0", END)
expression = expression.strip() # 去除空格和换行符
if expression.startswith('y='):
expression = expression[2:]
if 'sin' in expression or 'cos' in expression:
period = 4 * np.pi / abs(eval(expression.split('sin')[1] if 'sin' in expression else expression.split('cos')[1], {'x': 1}))
x = np.linspace(-period / 2, period / 2, 100) # 定义自变量的范围,共有 100 个点
else:
x = np.linspace(-10, 10, 50) # 定义自变量的范围,共有 201 个点
y = f(x, expression) # 计算原函数的因变量的取值
z = g(x, expression) # 计算一阶导函数的因变量的取值
# 绘制原函数和一阶导函数的图像
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
ax[0].plot(x, y) # 绘制原函数图像
ax[0].set_ylabel('y') # 设置 y 轴标签
ax[0].set_xlabel('x') # 设置 x 轴标签
ax[0].set_title('函数图像') # 设置子图标题
ax[1].plot(x, z) # 绘制一阶导函数图像
ax[1].set_ylabel('dy/dx') # 设置 y 轴标签
ax[1].set_xlabel('x') # 设置 x 轴标签
ax[1].set_title('一阶导数图像') # 设置子图标题
plt.tight_layout() # 自动调整子图布局
new_window = Toplevel() # 创建新窗口
new_window.title('图像') # 设置窗口标题
canvas = FigureCanvasTkAgg(fig, master=new_window) # 绘制画布
canvas.draw()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) # 将画布添加到窗口中
new_window.focus_set() # 聚焦到新窗口
new_window.grab_set() # 捕获所有事件
new_window.mainloop() # 进入消息循环
def update_chat_records():
global chat_listbox
chat_listbox.delete(0, END)
cursor.execute("SELECT * FROM chat_records")
records = cursor.fetchall()
for record in records:
chat_listbox.insert(END, f"{record[1]}: {record[2]}")
def show_chat_records():
global chat_listbox
new_window = Toplevel()
new_window.title('聊天记录')
new_window.geometry('500x400')
chat_listbox = Listbox(new_window, width=60, height=20)
chat_listbox.pack(pady=10)
scrollbar = Scrollbar(new_window)
scrollbar.pack(side=RIGHT, fill=Y)
chat_listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=chat_listbox.yview)
update_chat_records()
def close_chat_records():
new_window.destroy()
new_window.protocol("WM_DELETE_WINDOW", close_chat_records)
new_window.mainloop()
def delete_chat_records():
cursor.execute("DELETE FROM chat_records")
conn.commit()
update_chat_records()
messagebox.showinfo("删除聊天记录", "成功删除聊天记录!")
def modify_chat_record():
selected_index = chat_listbox.curselection()
if selected_index:
selected_record = chat_listbox.get(selected_index[0])
message_parts = selected_record.split(": ")
if len(message_parts) == 2:
sender = message_parts[0]
message = message_parts[1]
modify_window = Toplevel()
modify_window.title('修改聊天记录')
modify_window.geometry('300x150')
sender_label = Label(modify_window, text="发送者:")
sender_label.pack()
sender_entry = Entry(modify_window)
sender_entry.insert(END, sender)
sender_entry.pack()
message_label = Label(modify_window, text="消息内容:")
message_label.pack()
message_entry = Entry(modify_window)
message_entry.insert(END, message)
message_entry.pack()
def save_changes():
new_sender = sender_entry.get()
new_message = message_entry.get()
cursor.execute("UPDATE chat_records SET sender = ?, message = ? WHERE sender = ? AND message = ?",
(new_sender, new_message, sender, message))
conn.commit()
update_chat_records()
messagebox.showinfo("修改聊天记录", "成功修改聊天记录!")
modify_window.destroy()
save_button = Button(modify_window, text="保存", command=save_changes)
save_button.pack()
modify_window.mainloop()
else:
messagebox.showerror("修改聊天记录", "无法解析选定的聊天记录!")
def close_windows():
global running
running = False
clientsocket.close()
s.close()
chat_window.destroy()
root.quit()
def login():
username = username_entry.get()
password = password_entry.get()
if username == 'user' and password == 'password':
chat_window.deiconify()
root.withdraw()
else:
messagebox.showerror('Error', 'Invalid username or password')
def start_sending():
global send_flag
send_flag = True
send_message()
root = Tk()
root.title("ChatApp")
login_frame = Frame(root)
login_frame.pack(pady=20)
Label(login_frame, text="用户名:").grid(row=0, column=0, padx=10, pady=5, sticky=E)
username_entry = Entry(login_frame)
username_entry.grid(row=0, column=1)
Label(login_frame, text="密码:").grid(row=1, column=0, padx=10, pady=5, sticky=E)
password_entry = Entry(login_frame, show="*")
password_entry.grid(row=1, column=1)
Button(login_frame, text="登录", command=login).grid(row=2, column=0, pady=10)
Button(login_frame, text="取消", command=close_windows).grid(row=2, column=1)
root.geometry('250x420-700+200')
root.protocol("WM_DELETE_WINDOW", close_windows)
chat_window = Toplevel()
chat_window.title('ChatApp')
chat_window.geometry('700x420-450+130')
chat_window.withdraw()
chat_frame = Frame(chat_window)
chat_frame.pack(pady=10)
scrollbar = Scrollbar(chat_frame)
scrollbar.pack(side=RIGHT, fill=Y)
chat_message = Text(chat_frame, width=97, height=25, state=DISABLED, padx=5, pady=5, yscrollcommand=scrollbar.set)
chat_message.pack()
scrollbar.config(command=chat_message.yview)
input_frame = Frame(chat_window)
input_frame.pack(pady=10)
input_message = Text(input_frame, width=50, height=2, padx=5, pady=5)
input_message.pack(side=LEFT)
send_button = Button(input_frame, text="发送", command=start_sending)
send_button.pack(side=LEFT, padx=10)
plot_button = Button(input_frame, text="画图", command=show_graph)
plot_button.pack(side=LEFT, padx=10)
sqylite_button = Button(input_frame, text="聊天记录",command=show_chat_records)
sqylite_button.pack(side=LEFT,padx=10)
chat_window.protocol("WM_DELETE_WINDOW", close_windows)
receive_thread = threading.Thread(target=receive_messages)
receive_thread.start()
root.mainloop()
# 客户端代码
from tkinter import *
from tkinter import messagebox
import threading
import socket
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from math import *
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(('192.168.44.1', 1234))
send_flag = False
running = True
def receive_messages():
global running
while running:
try:
data = c.recv(1024).decode()
if data:
chat_message.configure(state=NORMAL)
chat_message.insert(END,"服务器:"+data + '\n')
chat_message.configure(state=DISABLED)
if data.startswith("Function:y="):
function_str=data[11:]
try:
x = np.linspace(-10, 10, 100) # 创建一个包含-10到10的100个数据点的数组
if "x" not in function_str:
raise ValueError("函数中未包含自变量 x")
y = eval(function_str) # 计算函数在x值上的y值
dy_dx = np.gradient(y, x) # 计算函数在x值上的一阶导数
# 绘制函数及其一阶导数的图像
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(x, y)
plt.title('Function')
plt.xlabel('x')
plt.ylabel('y')
plt.subplot(2, 1, 2)
plt.plot(x, dy_dx)
plt.title('First Derivative')
plt.xlabel('x')
plt.ylabel("dy/dx")
plt.tight_layout()
plt.show()
except Exception as e:
chat_message.insert(END, "计算出错:" + str(e) + '\n')
except ConnectionError:
break
# 将表达式转化为函数
def f(x, expression):
func = np.vectorize(lambda x: eval(expression))
return func(x)
# 求取函数的一阶导函数
def g(x, expression):
return np.gradient(f(x, expression), x)
def show_graph():
expression = input_message.get("1.0", END)
expression = expression.strip() # 去除空格和换行符
if expression.startswith('y='):
expression = expression[2:]
if 'sin' in expression or 'cos' in expression:
period = 4 * np.pi / abs(eval(expression.split('sin')[1] if 'sin' in expression else expression.split('cos')[1], {'x': 1}))
x = np.linspace(-period / 2, period / 2, 100) # 定义自变量的范围,共有 100 个点
else:
x = np.linspace(-10, 10, 50) # 定义自变量的范围,共有 201 个点
y = f(x, expression) # 计算原函数的因变量的取值
z = g(x, expression) # 计算一阶导函数的因变量的取值
# 绘制原函数和一阶导函数的图像
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))
ax[0].plot(x, y) # 绘制原函数图像
ax[0].set_ylabel('y') # 设置 y 轴标签
ax[0].set_xlabel('x') # 设置 x 轴标签
ax[0].set_title('函数图像') # 设置子图标题
ax[1].plot(x, z) # 绘制一阶导函数图像
ax[1].set_ylabel('dy/dx') # 设置 y 轴标签
ax[1].set_xlabel('x') # 设置 x 轴标签
ax[1].set_title('一阶导数图像') # 设置子图标题
plt.tight_layout() # 自动调整子图布局
new_window = Toplevel() # 创建新窗口
new_window.title('图像') # 设置窗口标题
canvas = FigureCanvasTkAgg(fig, master=new_window) # 绘制画布
canvas.draw()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) # 将画布添加到窗口中
new_window.focus_set() # 聚焦到新窗口
new_window.grab_set() # 捕获所有事件
new_window.mainloop() # 进入消息循环
def send_message():
global send_flag
if send_flag:
message = input_message.get("1.0", END).strip()
if message:
input_message.delete("1.0", END)
chat_message.configure(state=NORMAL)
chat_message.insert(END,"我:"+message + '\n')
chat_message.configure(state=DISABLED)
c.send(message.encode())
send_flag = False
def close_windows():
global running
running = False
c.close()
chat_window.destroy()
root.quit()
def login():
username = username_entry.get()
password = password_entry.get()
if username == 'user' and password == 'password':
chat_window.deiconify()
root.withdraw()
else:
messagebox.showerror('Error', 'Invalid username or password')
def start_sending():
global send_flag
send_flag = True
send_message()
root = Tk()
root.title("ChatApp")
login_frame = Frame(root)
login_frame.pack(pady=20)
Label(login_frame, text="用户名:").grid(row=0, column=0, padx=10, pady=5, sticky=E)
username_entry = Entry(login_frame)
username_entry.grid(row=0, column=1)
Label(login_frame, text="密码:").grid(row=1, column=0, padx=10, pady=5, sticky=E)
password_entry = Entry(login_frame, show="*")
password_entry.grid(row=1, column=1)
Button(login_frame, text="登录", command=login).grid(row=2, column=0, pady=10)
Button(login_frame, text="取消", command=close_windows).grid(row=2, column=1)
root.geometry('250x420-700+200')
root.protocol("WM_DELETE_WINDOW", close_windows)
chat_window = Toplevel()
chat_window.title('ChatApp')
chat_window.geometry('700x420-450+130')
chat_window.withdraw()
chat_frame = Frame(chat_window)
chat_frame.pack(pady=10)
scrollbar = Scrollbar(chat_frame)
scrollbar.pack(side=RIGHT, fill=Y)
chat_message = Text(chat_frame, width=97, height=25, state=DISABLED, padx=5, pady=5, yscrollcommand=scrollbar.set)
chat_message.pack()
scrollbar.config(command=chat_message.yview)
input_frame = Frame(chat_window)
input_frame.pack(pady=10)
input_message = Text(input_frame, width=50, height=2, padx=5, pady=5)
input_message.pack(side=LEFT)
send_button = Button(input_frame, text="发送", command=start_sending)
send_button.pack(side=LEFT, padx=10)
plot_button = Button(input_frame, text="画图", command=show_graph)
plot_button.pack(side=LEFT, padx=10)
sqylite_button = Button(input_frame, text="聊天记录")
sqylite_button.pack(side=LEFT,padx=10)
chat_window.protocol("WM_DELETE_WINDOW", close_windows)
receive_thread = threading.Thread(target=receive_messages)
receive_thread.start()
root.mainloop()
本项目指在设计一个基于python GUI编程,matplotlib画图,MySQL数据库操作以及网络通信图形界面的程序。源码如上,欢迎指正!