2017-05-14 71 views
0

请考虑下面的代码:Kivy布局背景不是画上滚动型

Builder.load_string(
""" 
<TestView>: 
    canvas.before: 
     Color: 
      rgba: 0, 1, 0, 1 
     Rectangle: 
      pos: self.pos 
      size: self.size 
""") 

class TestView(GridLayout): 

    def __init__(self, **kwargs): 
     super(TestView, self).__init__(**kwargs) 

     self.cols = 1 
     self.spacing = 20 

     self.add_widget(Label(text="I'm on the TestView", height=80)) 

class TestScreen(Screen): 

    def __init__(self, **kwargs): 
     super(TestScreen, self).__init__(**kwargs) 

     self.content_grid_layout = GridLayout(cols=1, spacing=20, size_hint_y=None) 
     self.content_grid_layout.bind(minimum_height=self.content_grid_layout.setter('height')) 

     self.content_grid_layout.add_widget(Label(text="A")) 
     self.content_grid_layout.add_widget(Label(text="B")) 

     self.content_grid_layout.add_widget(TestView()) 

     self.scroll_view = ScrollView(size_hint=(1, 1), size=(self.width, self.height)) 
     self.scroll_view.add_widget(self.content_grid_layout) 

     self.add_widget(self.scroll_view) 

sm = ScreenManager() 
sm.add_widget(TestScreen(name="test_screen")) 

class TestApp(App): 

    def build(self): 
     return sm 

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

(我已经离开了进口,节省空间)。所以我的具体问题是,我期望TestView的背景被涂成绿色,但它不在这里。这将是,如果你只需要添加TestView直接在屏幕上的布局,即改变TestScreen的初始化只是做:

self.content_grid_layout = GridLayout(cols=1, spacing=20, size_hint_y=None) 
self.content_grid_layout.add_widget(TestView()) 
self.add_widget(self.content_grid_layout) 

不过,我需要我的内容是在一个滚动型这里。所以,我也注意到,如果我只是注释掉该行:从原来的代码

self.content_grid_layout.bind(minimum_height=self.content_grid_layout.setter('height')) 

,一切似乎都如预期和TestView的背景漆成绿色工作。但是,如果我这样做了ScrollView没有做我期望的(它不滚动)。

如果我给TestView一个明确的高度,那么一切都按预期工作,例如,在TestView init中添加:

self.size_hint_y = None 
self.height = 40 

。所以我想这个问题并不是真的知道给TestView的高度,但是很奇怪的是,它能够将Label放在正确的位置,但不会绘制背景,或者将它从屏幕或其他东西上绘制出来。无论如何,对TestView进行硬编码对我来说不起作用,因为IRL会有一些动态内容会有不同的高度。

我觉得在一个健全的世界里,布局的高度应该是其内容的高度,除非另有说明,但也许这就是我。我想如果我可以调整TestView的大小,那么我会得到我期待的行为?


编辑:

OK,我想我可以把它按照这里介绍的策略做我想做什么:https://groups.google.com/d/msg/kivy-users/xRl2l8-1qLs/zzpk-QG4C0MJ (尤其是CustomGridLayout说明有它就像我的TestView我猜) 。

这么看来的基本想法是,我们设置自定义网格布局(TestView),以零高度开始,然后手动更新其对我们添加的每个孩子的高度,所以是这样的:

class TestView(GridLayout): 

    def __init__(self, **kwargs): 
     super(TestView, self).__init__(**kwargs) 

     self.cols = 1 
     self.spacing = 20, 20 

     self.size_hint_y = None 
     self.height = 0 

     self.height = self.height + 30 + self.spacing[1] 
     self.add_widget(Label(text="I'm on the TestView 1", size_hint_y=None, height=30)) 
     self.height = self.height + 30 + self.spacing[1] 
     self.add_widget(Label(text="I'm on the TestView 2", size_hint_y=None, height=30)) 
     self.height = self.height + 30 + self.spacing[1] 
     self.add_widget(Label(text="I'm on the TestView 3", size_hint_y=None, height=30)) 

我不会说谎,我觉得这很丑陋。看起来,布局应该能够在向它添加小部件时获得新的高度,而无需像这样进行填充。无论如何,它似乎工作。如果有人采取不太可怕的方式,我会打开这个问题。

回答

0

OK,我想我已经破解了 - 结合的TestView的爱德华达斯概念最小高度到它的高度是正确的(我想也许这应该是明显的,因为它也是我们为'content_grid_layout'所做的)。但是,它不起作用,因为我们也需要'size_hint_y:None'。

我不认为我们应该从'content_grid_layout'中取出高度/最小高度绑定,因为这会停止滚动工作。

这样做的效果与预期的一样,我们不必手动设置TestView的高度。这是一个完整的工作示例保存任何困惑 - 我从GridLayout到的BoxLayout改变TestView,但它可以作为一个网格布局太:

from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.screenmanager import ScreenManager, Screen 
from kivy.uix.label import Label 
from kivy.uix.button import Button 
from kivy.uix.gridlayout import GridLayout 
from kivy.uix.boxlayout import BoxLayout 
from kivy.uix.scrollview import ScrollView 

Builder.load_string(
""" 
<TestView>: 
    size_hint_y: None   # <----------------- MAKE SURE YOU DO THIS! 
    height: self.minimum_height # <----------------- AND THIS! 
    canvas.before: 
     Color: 
      rgba: 0, 0.8, 0.06, 0.5 
     RoundedRectangle: 
      pos: self.pos 
      size: self.size 
      radius: [16,16,16,16] 
""") 

class TestView(BoxLayout): 

    def __init__(self, **kwargs): 
     super(TestView, self).__init__(**kwargs) 

     self.orientation = 'vertical' 
     self.padding = [20, 20, 20, 20] 
     self.spacing = 20 

     self.add_widget(Label(text="I'm on the TestView 1")) 
     self.add_widget(Label(text="I'm on the TestView 2")) 
     self.add_widget(Label(text="I'm on the TestView 3")) 

class TestScreen(Screen): 

    def __init__(self, **kwargs): 
     super(TestScreen, self).__init__(**kwargs) 

     self.content_grid_layout = GridLayout(cols=1, spacing=20, size_hint_y=None) 
     self.content_grid_layout.bind(minimum_height=self.content_grid_layout.setter('height')) 

     # Give us something to scroll: 
     for i in range(20): 
      btn = Button(text=str(i), size_hint_y=None, height=40) 
      self.content_grid_layout.add_widget(btn) 
      if i == 5: 
       self.content_grid_layout.add_widget(TestView()) 

     self.scroll_view = ScrollView(size_hint=(1, 1), size=(self.width, self.height)) 
     self.scroll_view.add_widget(self.content_grid_layout) 

     self.add_widget(self.scroll_view) 

sm = ScreenManager() 
sm.add_widget(TestScreen(name="test_screen")) 

class TestApp(App): 

    def build(self): 
     return sm 

if __name__ == '__main__': 
    TestApp().run() 
0

通过注释掉您提到的行(self.content_grid_layout.bind(minimum_height=self.content_grid_layout.setter('height')))并将height: self.minimum_height添加到Builder字符串中,我可以使您的TestView变为绿色。 TestScreen也是可滚动的。

考虑更改TestScreen初始化到这一点:

def __init__(self, **kwargs): 
    super(TestScreen, self).__init__(**kwargs) 

    self.content_grid_layout = GridLayout(cols=1, spacing=20, size_hint_y=None) 
    # self.content_grid_layout.bind(minimum_height=self.content_grid_layout.setter('height')) 

    self.content_grid_layout.add_widget(Label(text="A")) 
    self.content_grid_layout.add_widget(Label(text="B")) 

    self.content_grid_layout.add_widget(TestView()) 

    self.scroll_view = ScrollView(size_hint=(1, 1), size=(self.width, self.height)) 
    self.scroll_view.add_widget(self.content_grid_layout) 

    self.add_widget(self.scroll_view) 

和建造串到这一点:

Builder.load_string(
""" 
<TestView>: 
    height: self.minimum_height 
    canvas.before: 
     Color: 
      rgba: 0, 1, 0, 1 
     Rectangle: 
      pos: self.pos 
      size: self.size 
""") 
+0

谢谢,但增加高度:self.minimum_height似乎没有什么区别。使用self.content_grid_layout.bind(minimum_height = self.content_grid_layout.setter('height'))线我没有得到绿色背景,没有它我会做,无论我们是否有身高:self.minimum_height和没有self.content_grid_layout.bind(minimum_height行滚动不起作用。我通过在https://kivy.org/docs/api-kivy.uix.scrollview.html添加一堆按钮来测试滚动。 – lemondifficult