在kivy中创建一个无限滚动视图图像

Create an infinite scrollview image in kivy

我正在尝试使用 kivy 创建一个数字笔记本应用程序。我有我的基本屏幕和我想使用的内衬 sheet 的 ScrollView。看起来不错,但我现在希望这个 sheet 是无限的——这意味着您可以继续向下滚动并拥有更多行(比如让图像垂直复制)。我怎样才能做到这一点?

非常感谢任何帮助:)

Python代码:

import kivy
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from PIL import Image as Image1
from kivy.uix.image import Image

GUI = Builder.load_file('style.kv')
img_size = Image1.open("images/notebook.png").size


class NotebookScreen(GridLayout):

    def __init__(self, **kwargs):
        self.rows = 1
        super(NotebookScreen, self).__init__(**kwargs)

    def get_size_for_notebook(self, **kwargs):
        global img_size
        width, height = Window.size
        return width, (img_size[0] * height / width)


class MainApp(App):

    def build(self):
        return NotebookScreen()


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

kv 文件:

<NotebookScreen>
    FloatLayout:
        rows: 2
        GridLayout:
            size_hint: 1, .05
            pos_hint: {"top": 1, "left": 1}
            id: tool_bar
            cols: 1
            canvas:
                Color:
                    rgba: 0, 0, 1, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
        GridLayout:
            id: notebook_grid
            size_hint: 1, .95
            pos_hint: {"top": .95, "left": .97}
            cols: 1


            ScrollView:
                do_scroll: (False, True)  # up and down

                Image:
                    id: notebook_image
                    source: 'images/notebook.png'
                    allow_stretch: True
                    keep_ratio: False
                    pos: self.pos
                    size: root.get_size_for_notebook()
                    size_hint: 1, None

您可以通过使用 BoxLayout 来保持内衬 sheet Image 来做到这一点。然后,您可以根据需要将相同 Image 的更多实例添加到 BoxLayout。这是执行此操作的代码版本:

from kivy.lang import Builder
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from PIL import Image as Image1
from kivy.uix.image import Image

#GUI = Builder.load_file('style.kv')
Builder.load_string('''
<NotebookScreen>
    FloatLayout:
        GridLayout:
            size_hint: 1, .05
            pos_hint: {"top": 1, "left": 1}
            id: tool_bar
            cols: 1
            canvas:
                Color:
                    rgba: 0, 0, 1, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
        GridLayout:
            id: notebook_grid
            size_hint: 1, .95
            pos_hint: {"top": .95, "left": 0}
            cols: 1

            MyScrollView:
                do_scroll: (False, True)  # up and down

                BoxLayout:
                    id: notebook_images
                    orientation: 'vertical'
                    size_hint: 1, None
                    height: self.minimum_height
                    MyImage:
<MyImage>:
    source: 'images/notebook.png'
    allow_stretch: True
    keep_ratio: True
    size_hint: None, None
    size: self.get_size_for_notebook()
''')

Window.size = (1000, 200)
img_size =Image1.open("images/notebook.png").size


class MyImage(Image):
    def get_size_for_notebook(self, **kwargs):
        global img_size
        width, height = Window.size
        return width, (img_size[0] * height / width)


class MyScrollView(ScrollView):
    def on_scroll_y(self, instance, scroll_val):
        if scroll_val < 0.05:  # no logic for this number
            box = App.get_running_app().root.ids.notebook_images
            new_image = MyImage()
            box.add_widget(new_image)
            self.scroll_y = new_image.height / box.height  # a more careful calculation may provide smoother operation


class NotebookScreen(GridLayout):
    def __init__(self, **kwargs):
        self.rows = 1
        super(NotebookScreen, self).__init__(**kwargs)


class MainApp(App):

    def build(self):
        return NotebookScreen()


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

使用Builder.load_string()而不是load_file()只是为了我自己方便。