0

テスト アプリケーションの概要:Scrollerスクロール可能なビュー ( という名前) と多くのフィールド ( という名前) を表示する Kivy アプリを作成していFieldます。これらの個別のフィールドを区別するのは非常に難しい場合があるため、各フィールドの背景色を交互に使用して、互いに区別しやすくすることにしました。私のテスト アプリケーションでは、20 の個別のフィールドを使用し、それぞれが濃い灰色と濃い灰色を交互に繰り返します。

トライアルのテスト: アプリケーションを起動すると、プログラムは見栄えがします。交互の背景は問題なく表示されます。下にスクロールしても、アプリケーションは問題なく表示されます。ただし、アプリケーションを上にスクロールすると、アプリケーションがおかしくなるようです。テキストはアプリケーションと共にスクロールしますが、背景はスクロールしません。さらに良いことに (皮肉なことに)、テキストは隣人の背景にフェードアウトし始めます。もう一度下にスクロールすると(最も遠いスクロールアップポイントのポイントを通過すると)、問題は消えたようです。

問題の簡単な説明:Fieldの「背景色」は、イベントのスクロール中にアプリケーションを台無しにします。

補足:スクロールしすぎると、アプリケーションが少し遅くなることにも気付きました。私は Kivy の描画サイクルにはあま​​り詳しくありませんが、背景をブリッティングしても過度に遅くなることはありません。

テスト アプリケーション:

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()
4

1 に答える 1

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()
于 2013-02-23T15:39:13.383 に答える