2

我正在开发一个 kivy 应用程序,该应用程序从 sqlite3 数据库中提取数据并用它填充 TreeView。当我展开几个组时,TreeView 变得太大而无法在我的屏幕上显示,所以我想将它放在 ScrollView 中,这样我仍然可以向下滚动并查看已离开屏幕底部的项目。我可以让一个基本的 ScrollView 工作,但是当我将 TreeView 放入其中时,没有滚动并且我的 TreeView 的顶部不在我的屏幕顶部。

我已将代码精简为这个没有 .kv 文件运行的问题的工作示例:

from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
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

class TreeViewButton(Button, TreeViewNode):
    pass

modGroups = [u'Fruit', u'Fruit', u'Meat', u'Dairy', u'Dairy', u'Fruit']
modItems = [u'Apple', u'Pear', u'Spam', u'Egg', u'Milk', u'Banana']
modDict = dict()
modDictUnique = dict()

def populate_tree_view(tv):
    modDict = zip(modGroups, modItems)
    print modGroups
    print 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='Food', 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 POSFMApp(App):

    def build(self):
        layout = GridLayout(cols=1, spacing=50, size_hint_y=None,width=800)
        layout.bind(minimum_height=layout.setter('height'))
        #for i in range(30):
        #    btn = Button(text=str(i), size=(480, 40),
        #                 size_hint=(None, None))
        #    layout.add_widget(btn)
        tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4, minimum_height=5000)
        populate_tree_view(tv)
        layout.add_widget(tv)
        root = ScrollView(size_hint=(None, None), size=(800, 700))
        root.center = Window.center
        root.add_widget(layout)
        return root

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

在我的实际应用程序中,modGroups 和 modItems 是从 sqlite3 数据库中填充的,但是这个示例提出了问题,而不必乱用 sqlite3。我输入了(注释掉的)行:

#for i in range(30):
#    btn = Button(text=str(i), size=(480, 40),
#                 size_hint=(None, None))
#    layout.add_widget(btn)

从这个kivy ScrollView 示例中显示,如果我取消注释这些行并注释掉关于我的 TreeView 的三行

tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4, minimum_height=5000)
populate_tree_view(tv)
layout.add_widget(tv)

然后,当我使用鼠标的滚轮时,我可以得到一个正常工作的 ScrollView,其右侧有一个滚动条。

我最好的猜测是 TreeView 没有告诉 ScrollView 它垂直的长度,所以 ScrollView 没有意识到它需要在 y 轴上滚动。不过,这只是一个猜测。

如何让 TreeView 在 ScrollView 内工作,以便可以滚动(尤其是在 y 轴上)通过 TreeView?

4

2 回答 2

4

a) 仅为一个孩子使用GridLayout,请不要。我会假设它是从何时/如果您添加更多孩子时遗留下来的。

b) TreeView的文档表明它具有minimun_height属性,该属性指示容纳所有子项所需的最小宽度/高度。Treeview不会根据孩子的数量自行改变它的高度。您应该(在这种情况下)将TreeView的高度更新为它的minimum_height ... tv.bind(minimum_height=tv.setter('height')) c)考虑到上述几点提供的信息,您可以这样做:

tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4)
tv.size_hint = 1, None
tv.bind(minimum_height = tv.setter('height'))
populate_tree_view(tv)
root = ScrollView(pos = (0, 0))
root.add_widget(tv)

这是包含这些更改的完整代码,因此可以将代码复制并粘贴到 .py 文件中并运行它。

from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
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

class TreeViewButton(Button, TreeViewNode):
    pass

modGroups = [u'Fruit', u'Fruit', u'Meat', u'Dairy', u'Dairy', u'Fruit']
modItems = [u'Apple', u'Pear', u'Spam', u'Egg', u'Milk', u'Banana']
modDict = dict()
modDictUnique = dict()

def populate_tree_view(tv):
    modDict = zip(modGroups, modItems)
    print modGroups
    print 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='Food', 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 POSFMApp(App):

    def build(self):
        #for i in range(30):
        #    btn = Button(text=str(i), size=(480, 40),
        #                 size_hint=(None, None))
        #    layout.add_widget(btn)
        tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4)
        tv.size_hint = 1, None
        tv.bind(minimum_height = tv.setter('height'))
        populate_tree_view(tv)
        root = ScrollView(pos = (0, 0))
        root.add_widget(tv)
        return root

if __name__ == '__main__':
    POSFMApp().run()
于 2013-04-26T00:08:20.350 回答
0

将高度添加到 TreeView 然后它将滚动。像这样。

ScrollView:
            id: kr_scroll
            do_scroll_x: False
            TreeView:
                id: trvMenu
                root_options: { 'text': 'Home', 'font_size': 15}
                hide_root: False
                indent_level: 4
                size_hint_y: None
                height: self.parent.height*2
于 2017-08-18T16:06:14.207 回答