如何从sqlite表填充Kivy树视图

1 投票
1 回答
4523 浏览
提问于 2025-04-17 19:59

我有什么

我有一个sqlite数据库,里面有两个表。第一个表有42个项目,包含一些字段,比如typeID(类型ID)、typeName(类型名称)、description(描述)、maxPrice(最高价格)和groupID(组ID),其中有4种不同的组ID。还有大约6个字段是后续计算需要的,但在树形视图中不需要用到。第二个表的结构类似,每个项目也有typeID、groupID、typeName、description、price(价格),以及8个额外的字段。关键是这两个表中的项目都是按组归类的。

我想要什么

我想从这两个表中填充一个kivy树形视图。组ID字段应该作为父节点,而所有拥有该组ID的类型ID则作为子节点。我可以直接把这些写死在代码里,但我的数据可能会变化(而且手动输入所有内容会很麻烦),所以我希望保持动态,这样如果我的表更新了,就可以自动重新生成树形视图。

大致想法

我的目标是让用户能够从第一个表生成的树形视图中选择一个项目,然后从第二个表生成的树形视图中选择多个项目(包括某个特定项目的重复项)。我现在的想法是,当用户从第一个树形视图中选择一个项目时,它会显示在其他小部件的顶部,然后当用户从第二个树形视图中选择一个项目时,它会显示在第一个项目的下面,并且有一个数量计数器,用户可以更改这个数量。限制是,第二个树形视图中所有项目的总价格不能超过第一个树形视图中所选项目的最高价格。

一个粗略的例子可能是这样的:

Item 3 from Tree View 1 maxPrice 10000
Item 1 from Tree View 2 price 1000 Qty 2
Item 3 from Tree View 2 price 3000 Qty 1
Item 4 from Tree View 2 price 500 Qty 4
Item 9 from Tree View 2 price 1000 Qty 2
price remaining 1000

在这个例子中,价格是(2*1000)+(1*3000)+(4*500)+(2*1000)=9000,这低于第一个树形视图中项目3的最高价格10000,因此这是可以的。如果用户尝试将第二个树形视图中项目3的数量改为2,应该显示剩余价格为-2000(也许可以把这个数字变成红色,让它更显眼)。

一旦我把两个树形视图搭建起来,我想我能搞定剩下的部分(或者我会再发一个问题!)我只是想提供这个“全局视角”,帮助给我的问题提供一些背景。

1 个回答

2

我已经为这个问题挣扎了好几个小时,终于搞出了一个大致能用的东西!我还是很想听听有什么办法可以让它更简洁一些。此外,界面上看起来有点笨重,按钮太大,而且没有滚动条(所以当你打开几个子树时,树的部分内容会超出屏幕底部,你就看不到了)。哦,对了,这只是我想做的两个树视图中的第二个,但这个比较难,所以第一个应该会简单很多。说完这些,我来分享一下代码:

from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.treeview import TreeView, TreeViewNode
from kivy.uix.treeview import TreeViewLabel
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.button import Button
import sqlite3
import os

POSdb = "C:\Users\User\Path\To\My\Database.db"

class TreeViewButton(Button, TreeViewNode):
    pass

modGroups = []
modItems = []
modDict = dict()
modDictUnique = dict()

def populate_tree_view(tv):
    conn = sqlite3.connect(POSdb)
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute('select * from ModuleTable')
    r = c.fetchall()
    for entry in r:
        modGroups.append(entry['groupID'])
        modItems.append(entry['typeName'])
    modDict = zip(modGroups, modItems)
    for k, v in modDict:
        if k not in modDictUnique:
            modDictUnique[k] = [v]
        else:
            modDictUnique[k].append(v)
    sortedGroups = modDictUnique.keys()
    sortedGroups.sort()
    #print modItems
    #print modDictUnique
    n = tv.add_node(TreeViewLabel(text='POS Mods', is_open=True))
    for group in sortedGroups:
        g = tv.add_node(TreeViewLabel(text='%s' % group), n)
        for item in modDictUnique[group]:
            tv.add_node(TreeViewButton(text='%s' % item), g)


class POSFM(FloatLayout):
    def __init__(self, **kwargs):
        super(POSFM, self).__init__(**kwargs)

        tv = TreeView(root_options=dict(text='Tree One'),
                      hide_root=True,
                      indent_level=4)

        populate_tree_view(tv)

        self.add_widget(tv)


class POSFMApp(App):

    def build(self):
        return POSFM()

if __name__ == '__main__':
    POSFMApp(width=800).run()

撰写回答