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

相关推荐
郁金香很忙1 小时前
新环境注册为Jupyter 内核
python·jupyter
张槊哲4 小时前
字符和编码(python)
linux·数据库·python
企鹅侠客7 小时前
写了个脚本将pdf转markdown
python·pdf·pdf转markdown
碳酸的唐7 小时前
PDF智能解析与知识挖掘:基于pdfminer.six的全栈实现
python·pdf·js
豌豆花下猫7 小时前
Python 潮流周刊#100:有了 f-string,为什么还要 t-string?(摘要)
后端·python·ai
于齐龙8 小时前
pip 常用命令及配置
linux·python·pip
高效匠人8 小时前
Python10天冲刺-设计模型之策略模式
开发语言·人工智能·python·策略模式
风暴之零9 小时前
文本中地理位置提取方法—正则和NLP模型
开发语言·python
Dxy12393102169 小时前
python合并word中的run
开发语言·python·word
hello_ejb39 小时前
聊聊Spring AI Alibaba的MermaidGenerator
人工智能·python·spring