2013-02-22 47 views
0

摘要:我写有滚动视图(名为Scroller)具有很多字段(名为Field)一Kivy应用来看待。这些单独的字段实际上很难区分,所以我决定为每个字段使用交替的背景颜色来帮助区分对方。我的测试应用程序使用20个单独的字段,每个字段在深灰色和深灰色之间交替。Kivy背景滚动视图测试应用程序的

测试试用版: 启动该应用程序,该程序看起来不错。交替的背景显得很好。即使当我向下滚动应用程序看起来很好。然而,当我在应用程序上滚动时,应用程序似乎变得怪异。文本与应用程序一起滚动,但背景不。甚至更好(讽刺),文本开始消失在他们的邻居背景。当我再次向下滚动时(通过最远的滚动点的点),问题似乎消失了。

简要问题描述:在向上滚动事件期间,Field的“背景颜色”混淆了应用程序。

附注:我也注意到,滚动过多后,应用程序有点迟缓。我对基维的抽签周期并不熟悉,但是分流背景不应该导致过度放缓。

测试应用程序:

import kivy 
kivy.require('1.0.7') 

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.graphics import Color, Rectangle 

class Main(App): 
    def build(self): 
     self.root = GridLayout(rows = 1) 
     self.root.add_widget(Scroller()) 
     return self.root 

class Scroller(ScrollView): 
    def __init__(self): 
     ScrollView.__init__(self) 
     self.view = GridLayout(cols = 1, size_hint = (1, None)) 
     self.add_widget(self.view) 
     self.view.bind(minimum_height = self.view.setter('height')) 

     for i in range(20): 
      self.view.add_widget(Field('Test field {}'.format(i),i%2 is 0)) 

class Field(GridLayout): 
    def __init__(self, name, bg): 
     assert isinstance(name, str) 
     assert isinstance(bg, bool) 
     self.bg = bg 
     GridLayout.__init__(self, 
          rows = 1, 
          padding = 10, 
          size = (0, 60), 
          size_hint = (1, None)) 
     self.add_widget(Label(text = name)) 
     self.add_widget(Button(text = 'Test button', 
           size = (200, 0), 
           size_hint = (None, 1))) 
     self.bind(pos = self.change_background) 
     self.bind(size = self.change_background) 

    def change_background(self, *args): 
     with self.canvas.before: 
      if self.bg: 
       Color(0.2, 0.2, 0.2, mode = 'rgb') 
      else: 
       Color(0.1, 0.1, 0.1, mode = 'rgb') 
      Rectangle(pos = self.pos, size = self.size) 

if __name__ in ('__main__', '__android__'): 
    app = Main() 
    app.run() 

回答

3
def change_background(self, *args): 
     self.canvas.before.clear()#<- clear previous instructions 
     with self.canvas.before: 
      if self.bg: 
       Color(0.2, 0.2, 0.2, mode = 'rgb') 
      else: 
       Color(0.1, 0.1, 0.1, mode = 'rgb') 
      Rectangle(pos = self.pos, size = self.size) 

您要添加/每次菲尔德的位置/大小的变化打桩指令到画布上,但不清除以前的指令。

您还应该考虑使用kv作为任何超过一小段代码的结果,为您节省大量时间。您可以使用kv转换您的代码,如下所示::

import kivy 
kivy.require('1.0.7') 

from kivy.app import App 
from kivy.uix.gridlayout import GridLayout 
from kivy.uix.scrollview import ScrollView 
from kivy.properties import ObjectProperty, BooleanProperty 
from kivy.lang import Builder 

Builder.load_string(''' 
<Scroller> 
    # root is Scroller here 
    # create a new ObjectProperty in kv that holds the ref to Gridlayout 
    # so you can access the instance in python code 
    view: glayout 
    GridLayout: 
     id: glayout 
     cols: 1 
     size_hint: (1, None) 
     height: self.minimum_height 

<Field> 
    canvas.before: 
     Color: 
      rgba: (0.2, 0.2, 0.2, 1) if self.bg else (0.1, 0.1, 0.1, 1) 
     Rectangle: 
      # binding properties is done implicitly and instructions aren't 
      # piled up while doing that. 
      pos: self.pos 
      # self here refers to Field as `self` is supposed to refer to the 
      # Widget not the drawing instruction 
      size: self.size 
    rows: 1 
    padding: 10 
    size: (0, 60) 
    size_hint: (1, None) 
    Label: 
     text: root.name 
    Button: 
     text: 'test button' 
     size: (200, 0) 
     size_hint: (None, 1) 
''') 


class Main(App): 

    def build(self): 
     self.root = GridLayout(rows = 1) 
     self.root.add_widget(Scroller()) 
     return self.root 


class Scroller(ScrollView): 
    def __init__(self, **kwargs): 
     super(Scroller, self).__init__(**kwargs) 
     for i in range(20): 
      # access self.view that was set in kv 
      self.view.add_widget(
           Field(
            name = 'Test field {}'.format(i), 
            bg = i%2 is 0)) 

class Field(GridLayout): 

    # use kivy's Properties so it becomes easier to observe and apply changes 
    # as a plus these can also be directly used in kv. As a advantage of using this now 
    # you can change name and bg dynamically and the changes should be reflected on 
    # screen 
    name = ObjectProperty('Test field uninitialized') 

    bg = BooleanProperty(False) 


if __name__ in ('__main__', '__android__'): 
    app = Main() 
    app.run()