代码之家  ›  专栏  ›  技术社区  ›  Zu Jiry

重置Kivy中的可选择标签

  •  0
  • Zu Jiry  · 技术社区  · 7 年前

    ScreenTest是一个屏幕,包含:
    -具有可选标签的视图
    -根据所选标签更改的标签
    -复位按钮

    重置按钮应该重置视图中所做的选择,但我不知道如何将所选的可选择标签设置为false。我无法访问任何ID或类来更改此参数
    我需要的是,通过单击“重置”按钮,视图中没有选择任何内容,因此标签中不会显示任何文本(或文本重置为“”,因为所选文本为空)。

    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 回复  |  直到 7 年前
        1
  •  1
  •   Kacperito    7 年前

    快速解决方案

    我相信最简单的方法是遍历回收框中的元素,如果选择了它们,则取消选择,并将文本设置为 "" . 考虑在 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()
    

    稍微好一点的方法

    打给孩子和家长的电话可能会在更复杂的布局中变得相当混乱,所以我想建议一种更干净的方法来解决您的问题。由于一次只处理一个选定的项,我认为最好的方法是将项本身存储在程序中,并在需要时从中检索信息。准确地说,不是储存 name_selected text_selected 在你的 test_view ,您只需存储所选项目。为此,必须引入一些更改:

    1. 进口 ObjectProperty StringProperty :

      from kivy.properties import BooleanProperty, ObjectProperty, StringProperty
      
    2. 增加一个 selected 归因于 测试视图 类,允许 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. 添加 选定的文本 已选择姓名 属性到 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. 删除不需要的属性( 选定的文本 , 已选择姓名 <TestView> :

      <TestView>:
          viewclass: 'SelectableLabel'