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

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

核心功能:病历信息录入(患者姓名、年龄、性别、诊断结果、主治医生),自动记录就诊时间,病历信息展示(使用Treeview表格),病历信息查询(按姓名搜索),数据sqlite3存储。

主要组件:输入表单:包含患者基本信息输入字段,功能按钮:添加、查询、保存、加载、清空,病历列表:以表格形式展示所有病历记录,双击支持:双击记录可自动填充到输入框。

数据库存储:使用SQLite3替代JSON文件存储,自动创建数据库表结构,使用参数化查询防止SQL注入。

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

高级查询

数据可视化

python 复制代码
# -*- 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 FigureCanvasTkAgg

class MedicalRecordSystem:
    def __init__(self, root):
        self.root = root
        self.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 cursor
        except 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("输入错误", "患者姓名和诊断结果不能为空!")
            return

        try:
            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("警告", "请先选择要修改的记录")
            return

        record_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 SET
                               name=?, 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("警告", "请先选择要删除的记录")
            return

        if 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] = entry

        def 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

相关推荐
rayufo4 小时前
【工具】列出指定文件夹下所有的目录和文件
开发语言·前端·python
Python 老手5 小时前
Python while 循环 极简核心讲解
java·python·算法
开源技术6 小时前
如何将本地LLM模型与Ollama和Python集成
开发语言·python
weixin_437044646 小时前
Netbox批量添加设备——堆叠设备
linux·网络·python
我有医保我先冲6 小时前
AI 时代 “任务完成“ 与 “专业能力“ 的区分:理论基础、行业影响与个人发展策略
人工智能·python·机器学习
测试开发Kevin7 小时前
小tip:换行符CRLF 和 LF 的区别以及二者在实际项目中的影响
java·开发语言·python
爱学习的阿磊7 小时前
使用PyTorch构建你的第一个神经网络
jvm·数据库·python
阿狸OKay7 小时前
einops 库和 PyTorch 的 einsum 的语法
人工智能·pytorch·python
编码者卢布8 小时前
【Azure Storage Account】Azure Table Storage 跨区批量迁移方案
后端·python·flask
可触的未来,发芽的智生8 小时前
狂想:为AGI代称造字ta,《第三类智慧存在,神的赐名》
javascript·人工智能·python·神经网络·程序人生