我只是在玩Python
和kivy
,根据kivy官方文档,我已经将String数据加载到RecyclerView
中。但是我在将对象像表单数据一样加载到列表中的多个列时遇到了麻烦。例如,我想将姓名,姓氏和年龄分成三列,标题标题逐行显示,我也尝试过RecyclerGridLayout
的三列标题,但是无论行与行的要求如何,它都只能将名称加载到网格中
<RV>:
viewclass: 'Label'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
将感谢任何提示或示例代码,以了解RecyclerView如何在kivy
上工作
答案 0 :(得分:2)
我也在寻找这个,但是找不到具体的例子,所以我提供了解决方案。正如el3ien所说,您将需要创建一个自定义类,该类将代表可选标签的每一行。
<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' # I have included two methods of accessing the labels
label2_text: 'label 2 text' # This is method 1
label3_text: 'label 3 text'
pos: self.pos
size: self.size
Label:
id: id_label1 # method 2 uses the label id
text: root.label1_text
Label:
id: id_label2
text: root.label2_text
Label:
id: id_label3
text: root.label3_text
在将数据应用到RV中时,您需要重组字典以反映标签布局
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
paired_iter = zip(items_1, items_2) # items_1 and items_2 are defined elsewhere
self.data = []
for i1, i2 in paired_iter:
d = {'label2': {'text': i1}, 'label3': {'text': i2}}
self.data.append(d)
最后,在refresh_view_attrs中,将指定绑定到每个标签的.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()
答案 1 :(得分:2)
我使用了@ el3ien的上述想法。我的代码在下面。
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
Builder.load_string('''
<RV>:
viewclass: 'myView'
RecycleBoxLayout:
default_size: None, dp(200)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<myView@BoxLayout>:
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
on_release:
Button:
size_hint: (1,1)
background_normal: 'C:/Users/Arsalan/Desktop/dummyImage2.jpg'
background_down: 'C:/Users/Arsalan/Desktop/dummyImage1.png'
text:
text_size: self.size
halign:
valign: 'middle'
Label:
size_hint: (1,0.3)
text: 'Product summary'
text_size: self.size
halign:
valign: 'middle'
canvas.before:
Color:
rgba: (0.6, 0.7, 0.4, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint :(1,0.01)
Label:
size_hint: (1,0.3)
text: 'Rs 600'
text_size: self.size
halign:
valign: 'middle'
BoxLayout:
orientation: 'vertical'
size_hint: (0.001,1)
BoxLayout:
orientation: 'vertical'
on_release:
Button:
size_hint: (1,1)
background_normal: 'C:/Users/Arsalan/Desktop/dummyImage2.jpg'
background_down: 'C:/Users/Arsalan/Desktop/dummyImage1.png'
text:
text_size: self.size
halign:
valign: 'middle'
Label:
size_hint: (1,0.3)
text: 'Product summary'
text_size: self.size
halign:
valign: 'middle'
canvas.before:
Color:
rgba: (0.6, 0.7, 0.4, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint :(1,0.01)
Label:
size_hint: (1,0.3)
text: 'Rs 600'
text_size: self.size
halign:
valign: 'middle'
''')
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'text': str(x)} for x in range(100)]
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()
尝试一下,让我知道您是否还有任何疑问。
答案 2 :(得分:1)
创建自定义类,而不是使用Label
作为视图类。那可能是带有两个框的水平框布局。
<CustomClass@BoxLayout>:
orientation: "horizontal"
Label:
Label:
答案 3 :(得分:0)
我想在表中添加标题行;而且,我正在尝试以下操作:
<RV>:
BoxLayout:
orientation: "vertical"
BoxLayout:
orientation: 'horizontal'
size_hint: 1, None
size_hint_y: None
height: 25
Label:
text: "Item"
Label:
text: "User ID"
Label:
text: "User Name"
BoxLayout:
RecycleView:
id: review
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
但是:SelectableRecycleBoxLayout然后更深入地进入层次结构,我不再得到表,只有标题...如何解决此问题?我仍然不太了解如何从python获取kv东西。 :-(