Kivy - 创建一个可扩展的 ScrollView

Posted

技术标签:

【中文标题】Kivy - 创建一个可扩展的 ScrollView【英文标题】:Kivy - creating a scalable ScrollView 【发布时间】:2017-08-28 22:23:50 【问题描述】:

我正在尝试创建一个滚动视图,在其中我通过下拉菜单选择一个选项,然后按 + 按钮将两个标签连续添加到滚动视图。到目前为止,这是我的代码:

from kivy.app import App
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput

from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

class CaloriesScreen(Screen):
    pass

class theScreenManager(ScreenManager):
    pass

root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

theScreenManager:
    CaloriesScreen:

<CaloriesScreen>:
    name: 'calories'
    BoxLayout:
        orientation: 'vertical'

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .3
            Button:
                text: '<'
                size_hint: .1, 1
                font_size: 75
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                on_release: app.root.current = 'main' 

            Label:
                text: 'Calories'
                halign: 'left'
                font_size: 50
                canvas.before:
                    Color:
                        rgb: 0.18, .5, .92
                    Rectangle:
                        pos: self.pos
                        size: self.size
            Widget:
                size_hint: .1, 1
                canvas.before:
                    Color:
                        rgb: 0.18, .5, .92
                    Rectangle:
                        pos: self.pos
                        size: self.size

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .4
            spacing: 50
            canvas.before:
                Color:
                    rgb: 0.8, 0.8, 0.8
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                text: 'Recipes'
                font_size: 30
                color: 0.18, .5, .92, 1


            Button:
                id: btn
                text: 'Select a recipe...'
                font_size: 30
                on_release: dropdown.open(self)
                height: '48dp'
                pos_hint:  'top' : 0.75
                size_hint: .8, .5

            DropDown:

                id: dropdown
                on_parent: self.dismiss()
                on_select: btn.text = ''.format(args[1])


                Button:
                    text: 'Simple Cheese Omelette'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('First Item')

                Button:
                    text: 'Burger'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Second Item')

                Button:
                    text: 'Tomato and Caper Linguine'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Third Item')


            Button:
                text: '+'
                font_size: 30
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                pos_hint:  'top' : 0.65
                size_hint: .1, .3
                #on_release:
            Widget:
                size_hint: .02, 1

        BoxLayout:
            orientation: 'horizontal'
            size_hint: 1, .2
            canvas.before:
                Color:
                    rgb: 0.18, .5, .92
                Rectangle:
                    pos: self.pos
                    size: self.size
            Label:
                text:'Food'
                color: (1, 1, 1, 1)
            Label:
                text:'Calories'
                color: (1, 1, 1, 1)

        ScrollView:
            scroll_timeout: 250
            scroll_distance: 20
            do_scroll_y: True
            do_scroll_x: False
            GridLayout:
                id: grid
                cols: 2
                spacing: 10
                padding: 10
                Label:
                    text:'Food'
                    color: (1, 1, 1, 1)
                Label:
                    text:'Calories'
                    color: (1, 1, 1, 1)


''')

class temprecipeapp(App):
    def build(self):
        return root_widget

if __name__ == "__main__":
    temprecipeapp().run()

滚动视图上的白色食物和卡路里标签是示例。理想情况下,它们会浮动到顶部,然后我可以从下拉列表中选择一个新选项并将更多内容添加到队列中。我该怎么办?目前,如果我在滚动视图中添加大量堆叠的标签,则滚动不会启用。

【问题讨论】:

【参考方案1】:

要创建一个适合两列 foodcalories 的项目,最好从表头“复制”行为,即 FoodCalories 并创建一个单独的容器他们作为FoodItem,这只是一个BoxLayout

FoodItem 将有两个StringProperties

食物 卡路里

您可以通过root.foodroot.calories 在 kv 中访问它们。

现在要直接在kv中创建这样的项目并将其放入ScrollView,您需要Factory,默认情况下不可用,因此导入。有了它,你基本上可以这样做:

Factory.MyWidget()

它会创建一个小部件实例,您需要将其传递给GridLayoutadd_widget 方法。

代码编辑:

...
from kivy.properties import StringProperty

...
root_widget = Builder.load_string('''
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
#:import Factory kivy.factory.Factory  # <- import Factory

...
            DropDown:

                id: dropdown
#                on_parent: self.dismiss()  <- don't do this
                on_select: btn.text = ''.format(args[1])


                Button:
                    text: 'Simple Cheese Omelette'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('First Item')

                Button:
                    text: 'Burger'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Second Item')

                Button:
                    text: 'Tomato and Caper Linguine'
                    size_hint_y: None
                    height: '48dp'
                    on_release: dropdown.select('Third Item')


            Button:
                text: '+'
                font_size: 30
                background_normal: ""
                background_color: 0.18, .5, .92, 1
                pos_hint:  'top' : 0.65
                size_hint: .1, .3
                on_release: grid.add_widget(Factory.FoodItem(food=btn.text, calories='10'))  <- add a new item

...
        ScrollView:
            scroll_timeout: 250
            scroll_distance: 20
            do_scroll_y: True
            do_scroll_x: False
            GridLayout:
                id: grid
                cols: 1  <- change cols
                size_hint_y: None
                height: self.minimum_height  <- make the layout resize itself
                spacing: 10
                padding: 10

<FoodItem>:
    size_hint_y: None 
    height: 20  <- set a size for the item
    Label:
        text: root.food
        color: (1, 1, 1, 1)
    Label:
        text: root.calories
        color: (1, 1, 1, 1)
''')

class FoodItem(BoxLayout):
    food = StringProperty('')
    calories = StringProperty('')

...

还可以考虑使用Spinner 而不是纯Dropdown,因为它使事情变得更容易(并且您将避免on_parent 行为)。

【讨论】:

以上是关于Kivy - 创建一个可扩展的 ScrollView的主要内容,如果未能解决你的问题,请参考以下文章

Kivy 创建桌面程序?

Kivy展开和折叠一个面板,以隐藏内部结构。

如何在 Ubuntu 中将 kivy 和 python 打包成可执行文件?

如何在缩略图库中制作可点击的 kivy 图像

KIVY python:在python代码中使按钮可点击

如何在 python kivy 中创建可滚动的 FloatLayout