当前位置: 首页 > news >正文

Python项目源码63:病历管理系统1.0(tkinter+sqlite3+matplotlib)

1.病历管理系统包含以下主要功能:

核心功能:病历信息录入(患者姓名、年龄、性别、诊断结果、主治医生),自动记录就诊时间,病历信息展示(使用Treeview表格),病历信息查询(按姓名搜索),数据sqlite3存储。
主要组件:输入表单:包含患者基本信息输入字段,功能按钮:添加、查询、保存、加载、清空,病历列表:以表格形式展示所有病历记录,双击支持:双击记录可自动填充到输入框。
数据库存储:使用SQLite3替代JSON文件存储,自动创建数据库表结构,使用参数化查询防止SQL注入。

2.使用说明:运行程序后会生成medical_records.db文件用于存储数据,输入患者信息后点击"添加病历"按钮保存,输入姓名等条件进行高级搜索,双击表格记录可将数据填充到输入框。
在这里插入图片描述
高级查询
在这里插入图片描述
数据可视化
在这里插入图片描述

# -*- coding: utf-8 -*-
# @Author : 小红牛
# 微信公众号:WdPython
import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime
from matplotlib import rcParams
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAggclass MedicalRecordSystem:def __init__(self, root):self.root = rootself.root.title("病历管理系统1.0")self.root.geometry("1000x800")# 初始化数据库self.conn = sqlite3.connect('medical_records.db')self.create_table()# 创建界面组件self.create_widgets()self.load_data()def create_table(self):cursor = self.conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS records (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER,gender TEXT,diagnosis TEXT,doctor TEXT,date TEXT)''')self.conn.commit()def create_widgets(self):# 输入区域input_frame = ttk.LabelFrame(self.root, text="病历信息输入")input_frame.pack(pady=10, padx=10, fill="x")labels = ["患者姓名:", "年龄:", "性别:", "诊断结果:", "主治医生:"]self.entries = {}for i, text in enumerate(labels):label = ttk.Label(input_frame, text=text)label.grid(row=i, column=0, padx=5, pady=5, sticky="e")entry = ttk.Entry(input_frame, width=40)entry.grid(row=i, column=1, padx=5, pady=5, sticky="w")self.entries[text.strip(":")] = entry# 按钮区域btn_frame = ttk.Frame(self.root)btn_frame.pack(pady=10)buttons = [("添加病历", self.add_record),("修改病历", self.update_record),("删除病历", self.delete_record),("高级搜索", self.advanced_search),("数据可视化", self.show_statistics),("清空输入", self.clear_entries)]for i, (text, command) in enumerate(buttons):btn = ttk.Button(btn_frame, text=text, command=command)btn.grid(row=0, column=i, padx=5)# 病历列表list_frame = ttk.LabelFrame(self.root, text="病历列表")list_frame.pack(pady=10, padx=10, fill="both", expand=True)columns = ("id", "name", "age", "gender", "diagnosis", "doctor", "date")self.tree = ttk.Treeview(list_frame, columns=columns, show="headings")headings = [("id", "ID"),("name", "患者姓名"),("age", "年龄"),("gender", "性别"),("diagnosis", "诊断结果"),("doctor", "主治医生"),("date", "就诊日期")]for col_id, col_text in headings:self.tree.heading(col_id, text=col_text)self.tree.column(col_id, width=100, anchor="center")vsb = ttk.Scrollbar(list_frame, orient="vertical", command=self.tree.yview)hsb = ttk.Scrollbar(list_frame, orient="horizontal", command=self.tree.xview)self.tree.configure(yscrollcommand=vsb.set, xscrollcommand=hsb.set)self.tree.grid(row=0, column=0, sticky="nsew")vsb.grid(row=0, column=1, sticky="ns")hsb.grid(row=1, column=0, sticky="ew")list_frame.grid_rowconfigure(0, weight=1)list_frame.grid_columnconfigure(0, weight=1)self.tree.bind("<Double-1>", self.on_item_double_click)# 数据库操作方法def execute_query(self, query, parameters=()):cursor = self.conn.cursor()try:cursor.execute(query, parameters)self.conn.commit()return cursorexcept Exception as e:self.conn.rollback()messagebox.showerror("数据库错误", str(e))return None# 核心功能实现def add_record(self):record = (self.entries["患者姓名"].get(),self.entries["年龄"].get(),self.entries["性别"].get(),self.entries["诊断结果"].get(),self.entries["主治医生"].get(),datetime.now().strftime("%Y-%m-%d %H:%M:%S"))if not record[0] or not record[3]:messagebox.showwarning("输入错误", "患者姓名和诊断结果不能为空!")returntry:self.execute_query('''INSERT INTO records (name, age, gender, diagnosis, doctor, date)VALUES (?,?,?,?,?,?)''', record)self.load_data()self.clear_entries()messagebox.showinfo("成功", "病历添加成功!")except Exception as e:messagebox.showerror("错误", f"添加失败:{str(e)}")def update_record(self):selected = self.tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要修改的记录")returnrecord_id = self.tree.item(selected[0], 'values')[0]new_data = (self.entries["患者姓名"].get(),self.entries["年龄"].get(),self.entries["性别"].get(),self.entries["诊断结果"].get(),self.entries["主治医生"].get(),record_id)try:self.execute_query('''UPDATE records SETname=?, age=?, gender=?, diagnosis=?, doctor=?WHERE id=?''', new_data)self.load_data()messagebox.showinfo("成功", "病历修改成功!")except Exception as e:messagebox.showerror("错误", f"修改失败:{str(e)}")def delete_record(self):selected = self.tree.selection()if not selected:messagebox.showwarning("警告", "请先选择要删除的记录")returnif messagebox.askyesno("确认", "确定要删除这条记录吗?"):record_id = self.tree.item(selected[0], 'values')[0]try:self.execute_query('DELETE FROM records WHERE id=?', (record_id,))self.load_data()messagebox.showinfo("成功", "记录已删除")except Exception as e:messagebox.showerror("错误", f"删除失败:{str(e)}")def advanced_search(self):search_window = tk.Toplevel(self.root)search_window.title("高级搜索")criteria = [("患者姓名", "name"),("最小年龄", "min_age"),("最大年龄", "max_age"),("性别", "gender"),("诊断结果", "diagnosis"),("主治医生", "doctor")]entries = {}for i, (label, key) in enumerate(criteria):ttk.Label(search_window, text=label + ":").grid(row=i, column=0, padx=5, pady=5)entry = ttk.Entry(search_window)entry.grid(row=i, column=1, padx=5, pady=5)entries[key] = entrydef perform_search():conditions = []params = []if entries['name'].get():conditions.append("name LIKE ?")params.append(f"%{entries['name'].get()}%")if entries['min_age'].get():conditions.append("age >= ?")params.append(int(entries['min_age'].get()))if entries['max_age'].get():conditions.append("age <= ?")params.append(int(entries['max_age'].get()))if entries['gender'].get():conditions.append("gender = ?")params.append(entries['gender'].get())if entries['diagnosis'].get():conditions.append("diagnosis LIKE ?")params.append(f"%{entries['diagnosis'].get()}%")if entries['doctor'].get():conditions.append("doctor LIKE ?")params.append(f"%{entries['doctor'].get()}%")query = "SELECT * FROM records"if conditions:query += " WHERE " + " AND ".join(conditions)cursor = self.execute_query(query, params)if cursor:results = cursor.fetchall()self.show_search_results(results)search_window.destroy()ttk.Button(search_window, text="搜索", command=perform_search).grid(row=len(criteria), columnspan=2)def show_search_results(self, results):result_window = tk.Toplevel(self.root)result_window.title("搜索结果")tree = ttk.Treeview(result_window, columns=("id", "name", "age", "gender", "diagnosis", "doctor", "date"),show="headings")headings = [("id", "ID"), ("name", "姓名"), ("age", "年龄"),("gender", "性别"), ("diagnosis", "诊断"),("doctor", "医生"), ("date", "日期")]for col_id, col_text in headings:tree.heading(col_id, text=col_text)tree.column(col_id, width=100)for record in results:tree.insert("", "end", values=record)tree.pack(fill="both", expand=True)def show_statistics(self):# 设置全局中文字体(解决中文显示问题)rcParams['font.sans-serif'] = ['SimHei']rcParams['axes.unicode_minus'] = False  # 解决负号显示问题stat_window = tk.Toplevel(self.root)stat_window.title("数据统计")# 年龄分布统计age_ranges = ["0-18", "19-30", "31-45", "46-60", "61+"]queries = [("0-18岁", "age BETWEEN 0 AND 18"),("19-30岁", "age BETWEEN 19 AND 30"),("31-45岁", "age BETWEEN 31 AND 45"),("46-60岁", "age BETWEEN 46 AND 60"),("61岁及以上", "age >= 61")]age_data = {}for label, condition in queries:cursor = self.execute_query(f"SELECT COUNT(*) FROM records WHERE {condition}")age_data[label] = cursor.fetchone()[0]# 常见疾病统计cursor = self.execute_query("SELECT diagnosis, COUNT(*) FROM records GROUP BY diagnosis ORDER BY COUNT(*) DESC LIMIT 10")disease_data = cursor.fetchall()# 创建统计图表fig = plt.Figure(figsize=(10, 6))# 年龄分布饼图ax1 = fig.add_subplot(121)ax1.pie(age_data.values(), labels=age_data.keys(), autopct='%1.1f%%')ax1.set_title('年龄分布')# 常见疾病柱状图ax2 = fig.add_subplot(122)diagnoses = [item[0] for item in disease_data]counts = [item[1] for item in disease_data]ax2.barh(diagnoses, counts)ax2.set_title('常见疾病TOP10')ax2.invert_yaxis()canvas = FigureCanvasTkAgg(fig, master=stat_window)canvas.draw()canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)def load_data(self):cursor = self.execute_query("SELECT * FROM records ORDER BY date DESC")if cursor:self.tree.delete(*self.tree.get_children())for row in cursor.fetchall():self.tree.insert("", "end", values=row)def clear_entries(self):for entry in self.entries.values():entry.delete(0, "end")def on_item_double_click(self, event):selected = self.tree.selection()if selected:values = self.tree.item(selected[0], 'values')self.clear_entries()self.entries["患者姓名"].insert(0, values[1])self.entries["年龄"].insert(0, values[2])self.entries["性别"].insert(0, values[3])self.entries["诊断结果"].insert(0, values[4])self.entries["主治医生"].insert(0, values[5])def __del__(self):self.conn.close()if __name__ == "__main__":root = tk.Tk()app = MedicalRecordSystem(root)root.mainloop()

完毕!!感谢您的收看

----------★★跳转到历史博文集合★★----------
我的零基础Python教程,Python入门篇 进阶篇 视频教程 Py安装py项目 Python模块 Python爬虫 Json Xpath 正则表达式 Selenium Etree CssGui程序开发 Tkinter Pyqt5 列表元组字典数据可视化 matplotlib 词云图 Pyecharts 海龟画图 Pandas Bug处理 电脑小知识office自动化办公 编程工具 NumPy Pygame

相关文章:

  • 泰迪杯特等奖案例学习资料:基于边缘计算与多模态融合的温室传感器故障自诊断系统设计
  • BBR 之 ProbeRTT 新改
  • 基于随机森林的糖尿病预测模型研究应用(python)
  • 颠覆者DeepSeek:从技术解析到实战指南——开源大模型如何重塑AI生态
  • 企业级分布式 MCP 方案
  • 单片机-STM32部分:0、学习资料汇总
  • HTML5+JavaScript实现连连看游戏之二
  • QT6(32)4.5常用按钮组件:Button 例题的代码实现
  • Exa MCP Server - AI 搜索服务中间件
  • 计算机网络01-网站数据传输过程
  • 第37课 绘制原理图——放置离页连接符
  • 【计算机视觉】三维视觉:Open3D:现代三维数据处理的全栈解决方案
  • 第4篇:服务层抽象与复用逻辑
  • Java 中 Unicode 字符与字符串的转换:深入解析与实践
  • 精益数据分析(38/126):SaaS模式的流失率计算优化与定价策略案例
  • DeepSeek构建非农预测模型:量化关税滞后效应与非线性经济冲击传导
  • 【STM32】定时器输入捕获
  • 【AI面试准备】元宇宙测试:AI+低代码构建虚拟场景压力测试
  • 铸铁划线平板:多行业的精密测量工具(北重铸铁平板厂家)
  • react js 查看字体效果
  • 天津航空一航班盘旋14圈才降落,客服:因天气影响
  • 赵厚均评《唐诗与唐代园林景观的审美建构研究》|林泉恣探历,风景暂徘徊
  • 澎湃读报丨解放日报8个版聚焦:牢记嘱托,砥砺奋进
  • 荣盛发展股东所持1.17亿股将被司法拍卖,起拍价约1.788亿元
  • 国新办发布《关于新冠疫情防控与病毒溯源的中方行动和立场》白皮书
  • 如何反击右翼思潮、弥合社会分裂:加拿大大选镜鉴