用 Python + wxPython 构建桌面租车管理系统:从数据库设计到图形界面实现

引言

本篇博客将带你深入剖析一个基于 PythonWxPythonSQLite租车管理系统 源码。通过分层解读数据库管理、对话框封装、各业务面板和主入口,我们不仅了解整体架构,还能掌握核心代码片段的实现细节与设计思路。
用 Python + wxPython 构建桌面租车管理系统:从数据库设计到图形界面实现_第1张图片


项目环境与结构

  • 语言:Python 3.x

  • GUI 框架:WxPython(含 wx.advflatnotebook 插件)

  • 数据库:SQLite,本地文件 car_rental.db

  • 目录结构

    car_rental/
    ├─ 代码.py          # 主程序(含 UI 与 DBManager)
    └─ car_rental.db       # SQLite 数据库(首次运行时自动创建)
    

程序入口即为 代码.py,其中定义了 DBManager、多个 wx.Dialogwx.Panel 以及主窗口 MainFrame


一、数据库管理层(DBManager)

DBManager 类负责与 SQLite 的所有交互,包括表初始化、字段迁移、CRUD 操作及统计接口。

1.1 表结构初始化

def _init_tables(self):
    c = self.conn.cursor()
    c.execute("""
      CREATE TABLE IF NOT EXISTS admin (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        username TEXT UNIQUE NOT NULL,
        password TEXT NOT NULL,
        role TEXT NOT NULL DEFAULT '管理员'
      )""")
    # customers、vehicles、rentals 同理
    self.conn.commit()

这里一次性创建了 admincustomersvehiclesrentals 四张表,并设置了主外键约束与默认值。

1.2 字段自动迁移

当版本迭代需要新增字段时,_migrate_vehicles()_migrate_rentals() 会检测当前表结构,动态执行 ALTER TABLE ADD COLUMN,确保旧数据库兼容新代码。

cols = [r["name"] for r in cur.execute("PRAGMA table_info(vehicles)")]
if "status" not in cols:
    cur.execute("ALTER TABLE vehicles ADD COLUMN status TEXT NOT NULL DEFAULT '可租'")
self.conn.commit()

1.3 核心 CRUD 与业务逻辑

  • 管理员管理get_users(), add_user(), update_user(), delete_user()

  • 客户管理get_customers(), add_customer(), update_customer(), delete_customer()

  • 车辆管理get_vehicles(fuel, transmission, price_range), add_vehicle(...), update_vehicle(...), delete_vehicle(vid)

  • 租赁管理

    • 查询所有租单:

      def get_rentals(self):
        return self.conn.execute("""
          SELECT r.id, c.name AS customer, v.plate||'/'||v.model AS vehicle,
                 a.username AS operator, r.start_date, r.end_date, 
                 r.total_price, r.status
          FROM rentals r
          JOIN customers c ON r.customer_id=c.id
          JOIN vehicles v ON r.vehicle_id=v.id
          JOIN admin a ON r.operator_id=a.id
        """).fetchall()
      
    • 新增租单:自动计算天数与总价,并更新车辆状态为“已租”

      sd_dt = datetime.strptime(sd, "%Y-%m-%d")
      days = (ed_dt - sd_dt).days + 1
      price = self.conn.execute("SELECT price FROM vehicles WHERE id=?", (vid,)).fetchone()[0]
      total = days * price
      
    • 归还操作:更新租单状态与车辆状态

1.4 统计接口

提供首页仪表盘所需数据,如总车辆数、可租/已租数量、本日/本月租赁数、近三日到期提醒等:

def available_vehicles(self):
    return self.conn.execute(
      "SELECT COUNT(*) FROM vehicles WHERE status='可租'"
    ).fetchone()[0]
def upcoming_returns(self):
    td = datetime.now().strftime("%Y-%m-%d")
    fu = (datetime.now()+timedelta(days=3)).strftime("%Y-%m-%d")
    return self.conn.execute("""
      SELECT c.name AS customer, v.plate||'/'||v.model AS vehicle, r.end_date
      FROM rentals r
      JOIN customers c ON r.customer_id=c.id
      JOIN vehicles v ON r.vehicle_id=v.id
      WHERE r.status='租赁中' AND r.end_date BETWEEN ? AND ?
      ORDER BY r.end_date
    """, (td, fu)).fetchall()

二、通用对话框封装

为了避免在多个面板中重复编写表单逻辑,引入了两种对话框类。

2.1 FormDialog

用于生成最基础的“字段—文本框”对话框,适合客户、管理员等简单信息录入。

class FormDialog(wx.Dialog):
    def __init__(self, parent, title, fields, init=None):
        super().__init__(parent, title=title)
        self.ctrls = {}
        vs = wx.BoxSizer(wx.VERTICAL)
        for f in fields:
            vs.Add(wx.StaticText(self, label=f), 0, wx.ALL, 5)
            tc = wx.TextCtrl(self, value=(init.get(f,"") if init else ""))
            self.ctrls[f] = tc
            vs.Add(tc, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
        # 标准按钮
        sdb = wx.StdDialogButtonSizer()
        # … 添加 “确定” 与 “取消”
        self.SetSizer(vs)

调用示例:

dlg = FormDialog(self, "添加客户", ["姓名", "电话", "邮箱"])
if dlg.ShowModal() == wx.ID_OK:
    data = dlg.get()  # 返回 {"姓名": "...", "电话": "...", ...}

2.2 VehicleDialog

FormDialog 基础上增添下拉框、日期控件与图片选择,专用于车辆信息录入/编辑。

class VehicleDialog(wx.Dialog):
    def __init__(self, parent, title, init=None):
        super().__init__(parent, title=title)
        # Plate、Model 等文本框
        # 下拉:fuel choices = ["全部","汽油","柴油","电"]
        # 日期:avail_start = wx.adv.DatePickerCtrl(...)
        # 图片:wx.FileDialog 选择后展示

统一提供 get() 方法,输出格式化的字段字典,进一步传递给 DBManager


三、各业务面板(Panel)

借助 wx.lib.agw.flatnotebook.FlatNotebook,系统分为五大选项卡:首页车辆管理客户管理租赁管理用户管理

3.1 HomePanel

  • 统计卡片:以 wx.StaticText + wx.BoxSizer 布局展示各统计接口返回的数字。
  • 到期提醒:使用 wx.ListCtrl 列表展示未来三天到期的租单。
  • 快速导航:九宫格按钮可一键切换到对应面板。

3.2 VehiclePanel2

  • 过滤功能:界面上方三组 wx.ComboBoxwx.TextCtrl 可按燃料、变速箱与价格区间筛选车辆列表。
  • 数据列表wx.ListCtrl 展示 platemodelfueltransmissionprice 等字段。
  • 图片预览:选中行后右侧加载该车辆的本地图片路径,并使用 wx.Bitmap 渲染。
  • 右键菜单:编辑、删除两项操作,通过 Bind(wx.EVT_CONTEXT_MENU) 触发 VehicleDialog 或删除确认。

核心刷新逻辑:

data = self.db.get_vehicles(fuel, transmission, price_range)
self.list_ctrl.DeleteAllItems()
for row in data:
    idx = self.list_ctrl.InsertItem(self.list_ctrl.GetItemCount(), row["plate"])
    # 依次 SetItemText 对其他列赋值

3.3 CustomerPanel2

与车辆管理类似,但仅包含 namephoneemail 三列,无图片与复杂过滤,复用 FormDialog 完成添加/编辑。

3.4 RentalPanel2

  • 租单录入区:上部依次选择客户、车辆、操作员、起止日期,动态计算天数及总价。
  • 租单列表wx.ListCtrl 展示历史租单,并可通过右键“一键归还”,恢复车辆状态。
  • 自动计算:在 start_dateend_date 变更时,以 datetime.strptime 解析并计算日期差,再乘以单价显示。

3.5 UserPanel2

仅对管理员账户进行管理,字段包括 usernamerole、可修改密码,保证只有授权用户能操作系统。


四、主窗口与事件流(MainFrame)

MainFrame 继承自 wx.Frame,使用 FlatNotebook 承载五个面板,并在启动时完成:

  1. 数据库初始化:实例化 DBManager,自动创建/迁移表结构。
  2. 面板实例化:将各 Panel 作为选项卡页添加到 FlatNotebook
  3. 事件绑定:如切换到车辆页时刷新列表,按钮点击切换面板等。
  4. 主循环启动app.MainLoop()

五、亮点与可拓展

  1. 零运维:SQLite 单文件数据库免安装,即插即用。

  2. 自动迁移:新增字段无缝兼容老数据,保障迭代升级平滑。

  3. 通用组件:封装 FormDialogVehicleDialog,极大减少重复代码。

  4. 界面体验FlatNotebook 选项卡结构直观,列表+右键菜单交互符合桌面应用习惯。

  5. 可扩展性

    • 切换至网络数据库(MySQL/PostgreSQL)实现多用户并发。
    • 引入权限控制模块,对不同角色细化操作权限。
    • 增加报表导出(Excel/PDF)与邮件自动发送功能。
    • 前端迁移到 Web 框架(Flask/Django + React/Vue)实现跨平台部署。

你可能感兴趣的:(python,数据库,jvm)