用 Python 的 Tkinter 库编写医院桌面程序

统医桌面

一个用来分发 Web 应用和 IT 自动化。够简单,200 行代码。https://github.com/tydesk/tydesk

欢迎 Fork 和 PR。


用 Python 的 Tkinter 库编写医院桌面程序
4 回复

想法很好,防统方程序有没有?我这里有个网络系统登陆器代码,加里面不知道合适不?一会我找找代码,参考这里 https://m.gitee.com/fallBirds/PESCMS-Login-GUI

另外如果能集成统一认证或者单点登陆就功能更好玩了,还有一个反正医院用,把危急值报警也加入,不知道有兴趣一起弄不?


我来给你一个用Tkinter创建医院管理系统的核心框架。这个程序包含了登录界面、主界面和几个基本功能模块。

import tkinter as tk
from tkinter import ttk, messagebox
import sqlite3
from datetime import datetime

class HospitalApp:
    def __init__(self, root):
        self.root = root
        self.root.title("医院管理系统")
        self.root.geometry("1000x600")
        
        # 创建数据库连接
        self.conn = sqlite3.connect('hospital.db')
        self.create_tables()
        
        # 显示登录界面
        self.show_login()
    
    def create_tables(self):
        """创建数据库表"""
        cursor = self.conn.cursor()
        
        # 用户表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                password TEXT NOT NULL,
                role TEXT NOT NULL
            )
        ''')
        
        # 患者表
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS patients (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                age INTEGER,
                gender TEXT,
                phone TEXT,
                address TEXT,
                register_date TEXT
            )
        ''')
        
        # 插入测试用户
        cursor.execute("INSERT OR IGNORE INTO users VALUES (1, 'admin', 'admin123', '管理员')")
        cursor.execute("INSERT OR IGNORE INTO users VALUES (2, 'doctor', 'doctor123', '医生')")
        
        self.conn.commit()
    
    def show_login(self):
        """显示登录界面"""
        self.clear_window()
        
        # 登录框架
        login_frame = ttk.Frame(self.root, padding="30")
        login_frame.pack(expand=True)
        
        ttk.Label(login_frame, text="医院管理系统登录", font=('Arial', 16)).grid(row=0, column=0, columnspan=2, pady=20)
        
        ttk.Label(login_frame, text="用户名:").grid(row=1, column=0, pady=10, sticky='e')
        self.username_var = tk.StringVar()
        ttk.Entry(login_frame, textvariable=self.username_var, width=25).grid(row=1, column=1, pady=10)
        
        ttk.Label(login_frame, text="密码:").grid(row=2, column=0, pady=10, sticky='e')
        self.password_var = tk.StringVar()
        ttk.Entry(login_frame, textvariable=self.password_var, show="*", width=25).grid(row=2, column=1, pady=10)
        
        ttk.Button(login_frame, text="登录", command=self.login, width=20).grid(row=3, column=0, columnspan=2, pady=20)
    
    def login(self):
        """处理登录"""
        username = self.username_var.get()
        password = self.password_var.get()
        
        cursor = self.conn.cursor()
        cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))
        user = cursor.fetchone()
        
        if user:
            self.current_user = {
                'id': user[0],
                'username': user[1],
                'role': user[3]
            }
            self.show_main_menu()
        else:
            messagebox.showerror("错误", "用户名或密码错误")
    
    def show_main_menu(self):
        """显示主菜单"""
        self.clear_window()
        
        # 菜单栏
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # 患者管理菜单
        patient_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="患者管理", menu=patient_menu)
        patient_menu.add_command(label="患者登记", command=self.register_patient)
        patient_menu.add_command(label="患者查询", command=self.search_patient)
        
        # 系统菜单
        system_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="系统", menu=system_menu)
        system_menu.add_command(label="退出", command=self.root.quit)
        
        # 主界面
        main_frame = ttk.Frame(self.root, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        welcome_label = ttk.Label(
            main_frame, 
            text=f"欢迎使用医院管理系统\n当前用户: {self.current_user['username']} ({self.current_user['role']})",
            font=('Arial', 14)
        )
        welcome_label.pack(pady=50)
        
        # 快速操作按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(pady=20)
        
        ttk.Button(button_frame, text="患者登记", command=self.register_patient, width=15).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="患者查询", command=self.search_patient, width=15).pack(side=tk.LEFT, padx=10)
    
    def register_patient(self):
        """患者登记界面"""
        self.clear_window()
        
        # 返回按钮
        ttk.Button(self.root, text="返回主菜单", command=self.show_main_menu).pack(anchor='nw', padx=10, pady=10)
        
        # 登记表单
        form_frame = ttk.LabelFrame(self.root, text="患者信息登记", padding="20")
        form_frame.pack(padx=20, pady=20, fill=tk.BOTH, expand=True)
        
        # 姓名
        ttk.Label(form_frame, text="姓名:").grid(row=0, column=0, pady=10, sticky='e')
        name_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=name_var, width=30).grid(row=0, column=1, pady=10)
        
        # 年龄
        ttk.Label(form_frame, text="年龄:").grid(row=1, column=0, pady=10, sticky='e')
        age_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=age_var, width=30).grid(row=1, column=1, pady=10)
        
        # 性别
        ttk.Label(form_frame, text="性别:").grid(row=2, column=0, pady=10, sticky='e')
        gender_var = tk.StringVar(value="男")
        gender_frame = ttk.Frame(form_frame)
        gender_frame.grid(row=2, column=1, pady=10, sticky='w')
        ttk.Radiobutton(gender_frame, text="男", variable=gender_var, value="男").pack(side=tk.LEFT)
        ttk.Radiobutton(gender_frame, text="女", variable=gender_var, value="女").pack(side=tk.LEFT)
        
        # 电话
        ttk.Label(form_frame, text="电话:").grid(row=3, column=0, pady=10, sticky='e')
        phone_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=phone_var, width=30).grid(row=3, column=1, pady=10)
        
        # 地址
        ttk.Label(form_frame, text="地址:").grid(row=4, column=0, pady=10, sticky='e')
        address_var = tk.StringVar()
        ttk.Entry(form_frame, textvariable=address_var, width=30).grid(row=4, column=1, pady=10)
        
        def save_patient():
            """保存患者信息"""
            if not name_var.get():
                messagebox.showerror("错误", "请输入患者姓名")
                return
            
            cursor = self.conn.cursor()
            cursor.execute('''
                INSERT INTO patients (name, age, gender, phone, address, register_date)
                VALUES (?, ?, ?, ?, ?, ?)
            ''', (
                name_var.get(),
                age_var.get() if age_var.get() else None,
                gender_var.get(),
                phone_var.get(),
                address_var.get(),
                datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            ))
            self.conn.commit()
            messagebox.showinfo("成功", "患者登记成功!")
            self.show_main_menu()
        
        # 保存按钮
        ttk.Button(form_frame, text="保存", command=save_patient, width=20).grid(row=5, column=0, columnspan=2, pady=20)
    
    def search_patient(self):
        """患者查询界面"""
        self.clear_window()
        
        # 返回按钮
        ttk.Button(self.root, text="返回主菜单", command=self.show_main_menu).pack(anchor='nw', padx=10, pady=10)
        
        # 搜索框
        search_frame = ttk.Frame(self.root)
        search_frame.pack(fill=tk.X, padx=20, pady=10)
        
        ttk.Label(search_frame, text="搜索患者:").pack(side=tk.LEFT)
        search_var = tk.StringVar()
        search_entry = ttk.Entry(search_frame, textvariable=search_var, width=30)
        search_entry.pack(side=tk.LEFT, padx=10)
        
        # 患者列表
        list_frame = ttk.LabelFrame(self.root, text="患者列表", padding="10")
        list_frame.pack(padx=20, pady=10, fill=tk.BOTH, expand=True)
        
        # 创建表格
        columns = ("ID", "姓名", "年龄", "性别", "电话", "登记时间")
        tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=15)
        
        # 设置列标题
        for col in columns:
            tree.heading(col, text=col)
            tree.column(col, width=100)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        
        tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        def load_patients(search_text=""):
            """加载患者数据"""
            # 清空现有数据
            for item in tree.get_children():
                tree.delete(item)
            
            cursor = self.conn.cursor()
            if search_text:
                cursor.execute("SELECT * FROM patients WHERE name LIKE ?", (f"%{search_text}%",))
            else:
                cursor.execute("SELECT * FROM patients ORDER BY register_date DESC")
            
            patients = cursor.fetchall()
            for patient in patients:
                tree.insert("", tk.END, values=patient)
        
        def on_search():
            """搜索患者"""
            load_patients(search_var.get())
        
        # 绑定搜索事件
        search_entry.bind('<Return>', lambda e: on_search())
        ttk.Button(search_frame, text="搜索", command=on_search).pack(side=tk.LEFT)
        
        # 加载初始数据
        load_patients()
    
    def clear_window(self):
        """清空窗口内容"""
        for widget in self.root.winfo_children():
            widget.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = HospitalApp(root)
    root.mainloop()

这个程序包含了几个核心功能:

  1. 用户登录系统:使用SQLite数据库存储用户信息,支持不同角色(管理员、医生)
  2. 患者管理
    • 患者信息登记(姓名、年龄、性别、联系方式等)
    • 患者信息查询和搜索
  3. 数据库集成:自动创建数据库和表结构
  4. 界面导航:清晰的界面切换逻辑

程序运行后会先显示登录界面,使用测试账号登录:

  • 管理员:admin/admin123
  • 医生:doctor/doctor123

登录后进入主界面,可以通过菜单或按钮访问患者登记和查询功能。所有数据都保存在本地的SQLite数据库中。

这个框架可以很容易地扩展,比如添加预约管理、病历管理、药品库存等功能。Tkinter虽然界面比较简单,但对于医院内部使用的桌面程序来说完全够用,而且部署方便,不需要额外的依赖。

建议先用这个框架跑起来,然后根据实际需求添加更多功能模块。

谢谢您的回复,看法很有见地。部分我也想了,也在打算做。为了易用和快速实现,先用了 1 个周末写了些代码而已。我们可以一起规划下。欢迎在 GitHub 进一步讨论

可以为医院提供基于位置的服务,这一点已经实现,防统方也需要,ITHelpDesk 也需要,安全审计也需要

回到顶部