【问题标题】:Scale with Kivy ScatterLayout Doesn't Behave as Expected使用 Kivy ScatterLayout 进行缩放的行为不符合预期
【发布时间】:2020-10-26 02:06:03
【问题描述】:

我想放大和缩小一组小部件。我也想滚动。我尝试使用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, 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, 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()

当缩小时,ScatterLayout 的子元素最终会超出布局的范围。无论转换是什么,我都希望所有孩子都保持在布局的范围内。我做错了什么?

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

【问题讨论】:

    标签: python scroll kivy scale


    【解决方案1】:

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

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

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

    class MyScrollView(ScrollView):
        pass
    
    <MyScrollView>:
        ...
    

    【讨论】:

      【解决方案2】:

      您必须缩放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, 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, 1
              Rectangle:
                  pos: 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()
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-01-27
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-10
        相关资源
        最近更新 更多