python - Kivy - python - 回收 View 行中的多个小部件

标签 python kivy

我想制作一个在每个回收 View 行中有多个标签的回收 View 。在我的具体示例中,我希望每行有 3 个标签:1 个标签包含项目索引,一个标签包含来自一个数据集的项目,另一个标签来自另一个数据集

在此示例中(取自 kivy 示例)我们有一个回收 View ,其中回收 View 中的每一行都包含一个标签:

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

Builder.load_string('''
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: True
        touch_multiselect: True
''')


items_1= {'apple', 'banana', 'pear', 'pineapple'}
items_2= {'dog', 'cat', 'rat', 'bat'}

class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, Label):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        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):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        self.data = [{'text': str(x)} for x in items_1]


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

if __name__ == '__main__':
    TestApp().run()

我希望每个回收 View 行都有 3 个标签:第一个标签是索引,第二个标签是 items_1,第三个标签是 items_2。像这样:

0 只苹果狗

1只香蕉猫

2梨鼠

3个菠萝 bat

谢谢!

最佳答案

我一直在寻找类似的解决方案,但找不到。我认为 PalimPalim 并没有真正回答这个问题,因为我认为 Ben t 正在寻找被视为单行的多个标签小部件。

在这种情况下,您为 GridLayout 使用自定义小部件并指定其结构。

<SelectableLabel>:
# Draw a background to indicate selection
canvas.before:
    Color:
        rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
    Rectangle:
        pos: self.pos
        size: self.size
label1_text: 'label 1 text'
label2_text: 'label 2 text'
label3_text: 'label 3 text'
pos: self.pos
size: self.size
Label:
    id: id_label1
    text: root.label1_text
Label:
    id: id_label2
    text: root.label2_text
Label:
    id: id_label3
    text: root.label3_text

在将数据应用到 RV 中时,您需要重组字典以反射(reflect)标签布局

class RV(RecycleView):
def __init__(self, **kwargs):
    super(RV, self).__init__(**kwargs)
    paired_iter = zip(items_1, items_2)
    self.data = []
    for i1, i2 in paired_iter:
        d = {'label2': {'text': i1}, 'label3': {'text': i2}}
        self.data.append(d)

最后,在 refresh_view_attrs 中,您将指定绑定(bind)到每个标签的 .label_text,或者您可以使用标签 ID。

def refresh_view_attrs(self, rv, index, data):
    ''' Catch and handle the view changes '''
    self.index = index
    self.label1_text = str(index)
    self.label2_text = data['label2']['text']
    self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
    return super(SelectableLabel, self).refresh_view_attrs(
        rv, index, data)

完整代码如下:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

Builder.load_string('''
<SelectableLabel>:
    # Draw a background to indicate selection
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size
    label1_text: 'label 1 text'
    label2_text: 'label 2 text'
    label3_text: 'label 3 text'
    pos: self.pos
    size: self.size
    Label:
        id: id_label1
        text: root.label1_text
    Label:
        id: id_label2
        text: root.label2_text
    Label:
        id: id_label3
        text: root.label3_text

<RV>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'
        multiselect: True
        touch_multiselect: True
''')


items_1 = {'apple', 'banana', 'pear', 'pineapple'}
items_2 = {'dog', 'cat', 'rat', 'bat'}


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
                                 RecycleBoxLayout):
    ''' Adds selection and focus behaviour to the view. '''


class SelectableLabel(RecycleDataViewBehavior, GridLayout):
    ''' Add selection support to the Label '''
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)
    cols = 3

    def refresh_view_attrs(self, rv, index, data):
        ''' Catch and handle the view changes '''
        self.index = index
        self.label1_text = str(index)
        self.label2_text = data['label2']['text']
        self.ids['id_label3'].text = data['label3']['text']  # As an alternate method of assignment
        return super(SelectableLabel, self).refresh_view_attrs(
            rv, index, data)

    def on_touch_down(self, touch):
        ''' Add selection on touch down '''
        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):
        ''' Respond to the selection of items in the view. '''
        self.selected = is_selected
        if is_selected:
            print("selection changed to {0}".format(rv.data[index]))
        else:
            print("selection removed for {0}".format(rv.data[index]))


class RV(RecycleView):
    def __init__(self, **kwargs):
        super(RV, self).__init__(**kwargs)
        paired_iter = zip(items_1, items_2)
        self.data = []
        for i1, i2 in paired_iter:
            d = {'label2': {'text': i1}, 'label3': {'text': i2}}
            self.data.append(d)
        # can also be performed in a complicated one liner for those who like it tricky
        # self.data = [{'label2': {'text': i1}, 'label3': {'text': i2}} for i1, i2 in zip(items_1, items_2)]


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

if __name__ == '__main__':
    TestApp().run()

关于python - Kivy - python - 回收 View 行中的多个小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45830039/

相关文章:

python - nbconvert 多索引数据帧到 latex

python - 使用 python 将文件转换为 BytesIO 对象

python - 当xaxis为timedelta时设置xlim

python - 如何根据Python中另一个 tkinter `Scale` 小部件的值来控制 tkinter `Scale` 小部件的值?

python - pytorch 中的列选择是可微分的吗?

python - 'with' 语句在 kivy 中如何工作?

python - Plyer 通知在 android 上不起作用

kivy - 增加 Kivy 中 MeshLinePlot 的线宽?

android - 如何在 Kivy 中添加滚动文本小部件?

android - 如何在 Kivy 中重置小部件