更改回收视图列的宽度

时间:2018-11-09 18:07:59

标签: python kivy recyclerview-layout

RecycleView给我带来了一些麻烦,尤其是将列更改为特定大小时。我在GridLayout上方用RecycleView编码了预期的列宽。当使用模数选择一个单元格时,我还提出了一种奇怪的方法来选择整行。我不确定这是否是最好的方法,但是我会喜欢别人对这种方法的看法。

我最终将希望能够删除整行,然后删除JSON文件中的选定数据。但是现在,我只希望宽度合适。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.storage.jsonstore import JsonStore
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior

kv_string = """

ScreenManager:
    id: manager

    Screen:
        BoxLayout:
            orientation: 'vertical'
            canvas:
                Color:
                    rgba: .2,.2,.5,1
                Rectangle:
                    pos: self.pos
                    size: self.size

            GridLayout:
                size_hint_y: .3
                cols:4
                MyButton:
                    text: 'Num'
                    size_hint_x: 0.5
                MyButton:
                    text: 'Ratings'
                MyButton:
                    text: 'Name'
                    size_hint_x: 2
                MyButton:
                    text: 'Score'
                    on_press:
                        #arrange the boxing in ascending or descending order

            RecycleView:
                data: [{'text': str(x)} for x in app.data]
                viewclass: 'SelectableLabel'

                SelectableRecycleGridLayout:
                    cols: 4
                    #default_size: None, dp(26)
                    default_size_hint: 1, None
                    size_hint_y: None
                    height: self.minimum_height
                    orientation: 'vertical'
                    multiselect: True
                    touch_multiselect: True

            ToggleButton:
                id: toggle_button
                size_hint_y: .3
                text: 'Delete Selected'
                state: 'normal'
                on_press:
                    app.data = [0]

<SelectableLabel>:
    canvas.before:
        Color:
            rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
        Rectangle:
            pos: self.pos
            size: self.size

<MyButton@Button>:
    background_color: 0,0,0,1
"""
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

        # *** This selects the whole row *** # Not sure if this is the best way.
        if self.collide_point(*touch.pos) and self.selectable:
            self.parent.select_with_touch(self.index, touch)
            if self.index % 4 == 0:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index + 2)
                self.parent.select_with_touch(self.index + 3)
                return
            elif self.index % 4 == 1:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index + 2)
                self.parent.select_with_touch(self.index -1)
                return
            elif self.index % 4 == 2:
                self.parent.select_with_touch(self.index + 1)
                self.parent.select_with_touch(self.index - 2)
                self.parent.select_with_touch(self.index -1)
                return
            elif self.index % 4 == 3:
                self.parent.select_with_touch(self.index - 1)
                self.parent.select_with_touch(self.index - 2)
                self.parent.select_with_touch(self.index - 3)
                return

    def apply_selection(self, rv, index, is_selected):
        self.selected = is_selected

        if App.get_running_app().root.ids.toggle_button.state == 'down':
            print('Deleted', index) #Still need to add delete function
            rv.layout_manager.clear_selection() #Not working
            self.remove_widget(index) #Also not working

class SelectableRecycleGridLayout(FocusBehavior, LayoutSelectionBehavior, RecycleGridLayout):
    pass

class MyApp(App):

    data = [] #ListProperty?

    store = JsonStore('file.json')
    store.put('Example: 1', value_1 = 'Rating: C', value_2 = 'Score: 10', value_3 = 'Name: Zack')
    store.put('Example: 2', value_1 = 'Rating: A', value_2 = 'Score: 32', value_3 = 'Name: Pete')
    store.put('Example: 3', value_1 = 'Rating: B', value_2 = 'Score: 24', value_3 = 'Name: Toby')
    store.put('Example: 4', value_1 = 'Rating: D', value_2 = 'Score: 03', value_3 = 'Name: Lars')

    x = 0

    for rows in store.keys():
        x += 1
        data.append(x)
        for row in store.get(rows):
            data.append(store.get(rows)[row])

    print(data) #shows successfully appended

    def build(self):
        root_widget = Builder.load_string(kv_string)
        return root_widget

if __name__ == "__main__":
    MyApp().run()

1 个答案:

答案 0 :(得分:1)

有种难看的骇客,但您可以在refresh_view_layout类中添加SelectableLabel方法:

def refresh_view_layout(self, rv, index, layout, viewport):
    mod = index % 4
    if mod == 0:
        layout['size_hint'] = (0.15, None)
    elif mod == 1:
        layout['size_hint'] = (0.225, None)
    elif mod == 2:
        layout['size_hint'] = (0.225, None)
    elif mod == 3:
        layout['size_hint'] = (0.4, None)
    super(SelectableLabel, self).refresh_view_layout( rv, index, layout, viewport)

因此,您可以将每个size_hint的{​​{1}}设置为所需的值。如果您使SelectableLabel与用于size_hint_x列标题的size_hint_x一致,我想您会得到想要的。