使用Kivy ScatterLayout进行缩放不符合预期

问题描述

我想放大和缩小一组小部件。我也想滚动。我尝试以ScrollView作为根小部件,以ScatterLayout作为子级来完成此操作。我要放大和缩小的小部件是ScatterLayout的子级。这不符合预期。这是最低版本。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.scatter import Scatter
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.scrollview import ScrollView


kv = '''
#:kivy 1.11.1
<MyScatter>:
    do_translation_y: False
    do_rotation: False
    do_scale: False
    canvas:
        Color:
            hsv: .1,1,.5
        Rectangle:
            size: 100,100

<ScrollView>:
    size_hint: None,None
    size: 640,480
    pos_hint: {'center_x': .5,'center_y': .5}
    scroll_type: ['bars']
    bar_width: 10
    bar_inactive_color: self.bar_color
    canvas:
        Color:
            rgb: 1,0
        Rectangle:
            pos: self.pos
            size: self.size

<MyScatterLayout>:
    size_hint: None,None
    size: 1280,720
    do_translation: False
    do_rotation: False
    pos_hint: {'center_x': 0.5,'center_y': 0.5}
    canvas:
        Color:
            rgb: 0,1
        Rectangle:
            pos: self.pos
            size: self.size
'''

Builder.load_string(kv)


class MyScatter(Scatter):
    pass


class MyScatterLayout(ScatterLayout):
    pass


class MyApp(App):
    def build(self):
        layout = MyScatterLayout()
        layout.add_widget(MyScatter())
        root = ScrollView()
        root.add_widget(layout)
        return root


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

child widget is outside scatterlayout

缩小时,ScatterLayout的子项最终超出布局范围。我希望所有的子代都不会超出布局的范围,无论转换是什么。我在做什么错了?

与问题相切:当我缩小到足以使ScatterLayout小于ScrollView时,滚动会将ScatterLayout捕捉到原点(左下角)。对于ScrollView docs,似乎ScrollView的孩子比ScrollView本身大。我假设为防止这种情况的发生,我需要在滚动时增加ScatterLayout的大小。

解决方法

不确定是否与问题有关,但是ScatterLayoutScatter的子类,因此其画布指令必须在本地坐标中。

<MyScatterLayout>:
    ...
    canvas:
        Color:
            rgb: 0,1
        Rectangle:
            pos: 0,0  # <- shold be this
            size: self.size

您不应该为ScrollView编写任何规则,因为它会影响代码外部可能存在的所有实例。因此,改为定义一个子类并为其编写规则。

class MyScrollView(ScrollView):
    pass

<MyScrollView>:
    ...
,

您必须缩放ScatterLayout的大小才能使孩子的位置保持一致。我还合并了Nattosai Mito's answer

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.scatter import Scatter
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.scrollview import ScrollView


kv = '''
#:kivy 1.11.1
<MyScatter>:
    do_translation_y: False
    do_rotation: False
    do_scale: False
    canvas:
        Color:
            hsv: .1,1,.5
        Rectangle:
            size: 100,100

<MyScrollView>:
    size_hint: None,None
    size: 640,480
    pos_hint: {'center_x': .5,'center_y': .5}
    scroll_type: ['bars']
    bar_width: 10
    bar_inactive_color: self.bar_color
    canvas:
        Color:
            rgb: 1,0
        Rectangle:
            pos: self.pos
            size: self.size

<MyScatterLayout>:
    size_hint: None,None
    size: 1280 * self.scale,720 * self.scale  # this is the correction
    do_translation: False
    do_rotation: False
    pos_hint: {'center_x': 0.5,'center_y': 0.5}
    canvas:
        Color:
            rgb: 0,0
            size: self.size
'''

Builder.load_string(kv)


class MyScatter(Scatter):
    pass


class MyScatterLayout(ScatterLayout):
    pass


class MyScrollView(ScrollView):
    pass


class MyApp(App):
    def build(self):
        layout = MyScatterLayout()
        layout.add_widget(MyScatter())
        root = MyScrollView()
        root.add_widget(layout)
        return root


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