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

相关推荐
踏着七彩祥云的小丑5 小时前
pytest——Mark标记
开发语言·python·pytest
不爱吃炸鸡柳6 小时前
Python入门第一课:零基础认识Python + 环境搭建 + 基础语法精讲
开发语言·python
Dxy12393102167 小时前
Python基于BERT的上下文纠错详解
开发语言·python·bert
SiYuanFeng8 小时前
Colab复现 NanoChat:从 Tokenizer(CPU)、Base Train(CPU) 到 SFT(GPU) 的完整踩坑实录
python·colab
炸炸鱼.9 小时前
Python 操作 MySQL 数据库
android·数据库·python·adb
_深海凉_10 小时前
LeetCode热题100-颜色分类
python·算法·leetcode
AC赳赳老秦10 小时前
OpenClaw email技能:批量发送邮件、自动回复,高效处理工作邮件
运维·人工智能·python·django·自动化·deepseek·openclaw
zhaoshuzhaoshu10 小时前
Python 语法之数据结构详细解析
python
AI问答工程师11 小时前
Meta Muse Spark 的"思维压缩"到底是什么?我用 Python 复现了核心思路(附代码)
人工智能·python
zfan52012 小时前
python对Excel数据处理(1)
python·excel·pandas