在Kivy的ScrollView中的TreeView - 无滚动

时间:2013-04-20 16:34:58

标签: python-2.7 kivy

我正在开发一个kivy app,它从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 example显示如果我取消注释这些行并注释掉关于我的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中工作,以便我可以通过TreeView滚动(特别是在y轴上)?

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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