在kivy重置SelectableLabel

时间:2018-06-03 14:13:02

标签: kivy

ScreenTest是一个屏幕,其中包含:
- 带可选标签的视图
- 根据所选标签而变化的标签
- 重置按钮

重置按钮应该重置视​​图中的选择,但我不知道如何选择SelectableLabel,然后将其“is_selected”设置为False。没有我可以访问的id或类来更改此参数
我需要的是,通过单击重置按钮,视图中没有任何内容被选中,因此标签中没有显示文本(或文本被重置为“”,因为text_selected为空)。

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.label import Label
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_string("""

<ScreenTest>:
    BoxLayout:
        TestView:
            id: test_view

        Label:
            id: text_lbl
            text: "" if not test_view.text_selected else test_view.text_selected 


        Button:
            id: reset_btn
            on_press: print("Wow")


<TestView>:
    viewclass: 'SelectableLabel'
    text_selected: ''
    name_selected: ''

    SelectableRecycleBoxLayout:
        id: culture_sub_view_layout
        orientation: 'vertical'
        default_size: None, dp(32)
        default_size_hint: .6, None
        size_hint: 1, .9
        multiselect: False
        touch_multiselect: False


<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.05, 0.5, .9, .8) if self.selected else (.5, .5, .5, 1)
        Rectangle:
            pos: self.pos
            size: self.size
""")


class TestView(RecycleView):
    def __init__(self, **kwargs):
        super(TestView, self).__init__(**kwargs)
        self.data =  [
            {"text": "Test1", "description": "Test1.text"},
            {"text": "Test2", "description": "Test2.text"},
            {"text": "Test3", "description": "Test3.text"}
        ]


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    pass


class SelectableLabel(RecycleDataViewBehavior, Label):
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
            rv.name_selected = rv.data[index]['text']
            rv.text_selected = rv.data[index]['description']
        else:
            print("selection removed for {0}".format(rv.data[index]))


class ScreenTest(Screen):
    pass


sm = ScreenManager()
sm.add_widget(ScreenTest(name='menu'))


class TestApp(App):
    def build(self):
        return sm


test_app = TestApp()
test_app.run()

谢谢!

1 个答案:

答案 0 :(得分:1)

快速解决方案

我认为最简单的方法是迭代回收框中的元素,如果选中它们则取消选择它们并将文本设置为""。考虑在TestView类中声明的以下函数:

def remove_selection(self):
    # Remove text
    self.parent.children[1].text = ""

    # Remove selection
    for child in self.children[0].children:
        if child.selected:
            child.selected = False

当然,您必须在按下按钮时调用它,您可以将布局更改为:

Button:
    id: reset_btn
    on_press: test_view.remove_selection()

稍微好一点

在更复杂的布局中,给孩子和家长打电话会变得非常混乱,所以我想建议一种更清洁的方法来解决你的问题。由于您一次只处理1个选定的项目,我认为最好的方法是将项目本身存储在您的程序中,并在需要时从中检索信息。确切地说,您可以简单地存储所选项目,而不是在name_selected中存储text_selectedtest_view。要做到这一点,必须引入一些变化:

  1. 导入ObjectPropertyStringProperty

    from kivy.properties import BooleanProperty, ObjectProperty, StringProperty
    
  2. selected课程中添加TestView属性,允许None有助于检查是否有任何内容被选中:

    class TestView(RecycleView):
        selected = ObjectProperty(None, allownone=True)
    
  3. 编辑上面提到的remove_selection方法:

    def remove_selection(self):
        # Remove selection
        if self.selected is not None:
            self.selected.selected = False
            self.selected = None
    
  4. text_selectedname_selected属性添加到SelectableLabel类:

    class SelectableLabel(RecycleDataViewBehavior, Label):
        index = None
        selected = BooleanProperty(False)
        selectable = BooleanProperty(True)
        text_selected = StringProperty()
        name_selected = StringProperty()
    
  5. 修改apply_selection方法:

    def apply_selection(self, rv, index, is_selected):
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
            # Store selected text and name inside the label
            self.name_selected = rv.data[index]['text']
            self.text_selected = rv.data[index]['description']
            # Remember the selection
            rv.selected = self
        else:
            print("selection removed for {0}".format(rv.data[index]))
    
  6. 更改text_lbl中显示的文字:

    Label:
        id: text_lbl
        text: "" if test_view.selected is None else test_view.selected.text_selected
    
  7. text_selected移除不需要的属性(name_selected<TestView>):

    <TestView>:
        viewclass: 'SelectableLabel'