Python 基于 sqlite 数据库值的依赖组合框

Python dependant combobox based on sqlite DB values

我是 python 的新手,我正在尝试使用 GUI 制作预算跟踪应用程序。为此,我输入了我在该计划中花费的每一笔金额。这些金额存储在一个 sqlite 数据库中,其中每个金额都有一个通用类别,每个类别都有多个子类别。这将可以根据链接到每个输入金额的类别和子类别生成统计信息。

我可以 select 所有可能的类别和子类别都存储在一个 sqlite 数据库中,这些可以 select 通过组合框在 GUI 中编辑。我的objective是当我select分类组合框中的某个分类时,子分类组合框中只显示链接到该分类的子分类。

我遇到的问题是我无法引用类别组合框中的值 selected 来过滤子类别组合框中可见的值。

我的代码中导致问题的部分如下:

query = c.execute('SELECT Name_Subcategory FROM Subcategory WHERE ID_Category == Categorybox.get()')

当我将 "Categorybox.get()" 更改为可以在我的 sqlite 数据库(例如 2)中找到的 ID_Category 时,代码有效并且子类别组合框中的可能子类别被过滤以仅显示那些ID_Category 值为“2”的子类别。

有谁知道解决这个问题的方法吗? 提前感谢您提供的任何建议。


概览 Gui 和 DB 表

#connect database
conn = sqlite3.connect("Budget.db")

#create cursor
c = conn.cursor()


# Combobox_Category
def Cat_opt():
    conn = sqlite3.connect('Budget.db')
    query = c.execute('SELECT Name_Category FROM Category')
    data = []
    for row in c.fetchall():
        data.append(row[0])
    return data
    conn.close(row=1, column=0)

Category_box = Combobox(width=27)
Category_box['value'] = Cat_opt()

# Combobox_Subcategory
def Subcat_opt():
    conn = sqlite3.connect('Budget.db')
    query = c.execute('SELECT Name_Subcategory FROM Subcategory WHERE ID_Category == Categorybox.get()')
    data = []
    for row in c.fetchall():
        data.append(row[0])
    return data
    conn.close(row=1, column=0)

Subcategory_box = Combobox(width=27)
Subcategory_box['value'] = Subcat_opt()

Question: Based on the selected option in the first Combobox, query from a sqlite3 table the values of the second Combobox.


核心点

  1. 绑定事件回调'<<ComboboxSelected>>'

    self.bind('<<ComboboxSelected>>', self.on_selected)
    
  2. 查询选中项的id传给SubCategory.configure(query=<id>)

    def on_selected(self, event):
        _query = 'SELECT id FROM Category WHERE name == "{}"'.format(self.get())
        self.subcategory.configure(query=self.db.query(_query)[0])
    
  3. 根据id查询name,配置SubCategory(Combobox)values

    def configure(self, cnf=None, **kw):
        ...
            _query = 'SELECT name FROM SubCategory WHERE ID_Category == {}'.format(_query)
            super().configure(values=self.db.query(_query))
    

进口和数据

import tkinter as tk
import tkinter.ttk as ttk
import sqlite3


class DB:
    conn = None

    def __init__(self):
        if not DB.conn:
            DB.conn = sqlite3.connect(':memory:')

            print('DB.__init__()'.format())
            cur = DB.conn.cursor()
            cur.execute("CREATE TABLE IF NOT EXISTS Category(name TEXT, id INTEGER)")

            for _id, name in enumerate(('Revenues', 'Assets', 'Living expenses'), 1):
                cur.execute("INSERT INTO Category(id, name) VALUES (?,?)", (_id, name))

            cur.execute("CREATE TABLE IF NOT EXISTS SubCategory(name TEXT, id INTEGER, ID_Category INTEGER)")
            for _id, name in enumerate(('Salary', 'Saving account', 'Interest costs'), 1):
                cur.execute("INSERT INTO SubCategory(id, name, ID_Category) VALUES (?,?,?)", (_id, name, _id))

    def query(self, query):
        cur = DB.conn.cursor()
        return [record[0] for record in cur.execute(query)]

自定义组合框类别

class Category(ttk.Combobox):
    def __init__(self, parent, **kwargs):
        self.subcategory = kwargs.pop('subcategory', None)
        self.db = kwargs.pop('db', None)

        # defaults
        kwargs['width'] = kwargs.get('width', 27)
        super().__init__(parent, values=(), **kwargs)

        self.configure(values=self.db.query('SELECT name FROM Category'))
        self.bind('<<ComboboxSelected>>', self.on_selected)

    def on_selected(self, event):
        _query = 'SELECT id FROM Category WHERE name == "{}"'.format(self.get())
        self.subcategory.configure(query=self.db.query(_query)[0])

自定义组合框子类别

class SubCategory(ttk.Combobox):
    def __init__(self, parent, **kwargs):
        self.db = kwargs.pop('db', None)

        # defaults
        kwargs['width'] = kwargs.get('width', 27)
        super().__init__(parent, values=(), **kwargs)

    def configure(self, cnf=None, **kw):
        _query = kw.pop('query', None)
        if _query is not None:
            _query = 'SELECT name FROM SubCategory WHERE ID_Category == {}'.format(_query)
            super().configure(values=self.db.query(_query))
            self.event_generate('<Button-1>')
        else:
            super().configure(cnf, **kw)

用法

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('200x200')

        self.db = DB()

        subcategory = SubCategory(self, db=self.db)
        category = Category(self, subcategory=subcategory, db=self.db)

        category.pack()
        subcategory.pack()

        category.event_generate('<Button-1>')


if __name__ == "__main__":
    App().mainloop()

测试 Python:3.5 - 'TclVersion':8.6 'TkVersion':8.6