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

相关推荐
麦烤楽鸡翅20 小时前
挡住洪水 (牛客)
java·数据结构·c++·python·算法·bfs·牛客
用户37215742613520 小时前
如何使用Python高效转换Excel到HTML
python
ashuicoder20 小时前
Python 函数传参与 JavaScript 对比
python
kyle-fang20 小时前
pytorch-张量
人工智能·pytorch·python
PKNLP20 小时前
11.大模型Agent应用
python·agent·pip
woshihonghonga21 小时前
Dropout提升模型泛化能力【动手学深度学习:PyTorch版 4.6 暂退法】
人工智能·pytorch·python·深度学习·机器学习
java1234_小锋21 小时前
PyTorch2 Python深度学习 - 循环神经网络(RNN)实例
python·rnn·深度学习·pytorch2
Danceful_YJ21 小时前
28. 门控循环单元(GRU)的实现
pytorch·python·深度学习
三排扣21 小时前
手搓transformer
pytorch·python·transformer
ZhengEnCi21 小时前
P3B-90%初学者参数传错位置?合格程序员都这样选择参数类型
python