Сбросить SelectableLabel в киви - PullRequest
0 голосов
/ 03 июня 2018

ScreenTest - это экран с:
- видом с выбираемыми метками
- меткой, которая изменяется в зависимости от выбранной метки
- кнопкой сброса

кнопка сброса должнасбросить выбор, сделанный в представлении, но я не знаю, как выбрать SelectableLabel, а затем установить его "is_selected" в False.У меня нет идентификатора или класса, к которому я мог бы получить доступ для изменения этого параметра
Что мне нужно, так это то, что при нажатии кнопки сброса ничего в представлении не выбирается, и поэтому текст не отображается в метке (или текст сбрасывается на"", поскольку 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 голосов
/ 03 июня 2018

Быстрое решение

Я полагаю, что самым простым способом было бы перебирать элементы внутри поля корзины, отменить их выбор, если они были выбраны, и установить текст на "".Рассмотрим следующую функцию, объявленную в вашем 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_selected в вашем test_view, вы можете просто сохранить выбранный элемент.Для этого необходимо внести ряд изменений:

  1. Импорт ObjectProperty и StringProperty:

    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_selected и name_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'
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...