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()
答案 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
一致,我想您会得到想要的。