python-3.x - Kivy 中的依赖循环视图
问题描述
我的问题:我想要两个 RecycleView,第二个(CultureSubView)取决于第一个(CultureView)中单击的内容。
每当单击 CultureView 中的某些内容时,它可以调用 CultureSubView 的“更新”功能,但我不知道该怎么做。
因为这必须在 SelectableLabel (这可能需要一个额外的 SelectableLabel 因为 CultureView 不需要额外的功能)
或在 kivy 语言的 CultureView 中完成。
我还尝试找到任何可以在 CultureView 中触发“on_press”的东西,然后更新 CultureSubView,但我也没有找到任何选项。这个想法在代码中被注释掉了。
from kivy.app import App
from kivy.properties import StringProperty, BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.lang import Builder
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
from kivy.uix.scrollview import ScrollView
Builder.load_string('''
<ScreenCulture>:
BoxLayout:
orientation: 'vertical'
Label:
pos_hint: {"x": .45, "top": 1}
text: "Testosterone"
size_hint: .1, .1
GridLayout:
id: culture_layout
rows: 1
cols: 3
padding: dp(10)
spacing: dp(10)
orientation: 'horizontal'
CultureView:
id: culture_list_view
# on_press? culture_sub_view.update()
CultureSubView:
id: culture_sub_view
name_selected:
"Planet" if not culture_list_view.name_selected else culture_list_view.name_selected
CultureLabel:
id: culture_text
name_selected: "NVM" if not culture_sub_view.name_selected else culture_sub_view.name_selected
text_selected: "This is totally a test text" if not culture_sub_view.text_selected else culture_sub_view.text_selected
<CultureView>:
viewclass: 'SelectableLabel'
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureSubView>:
viewclass: 'SelectableLabel'
text_selected: ''
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureLabel>:
size_hint_y: .85
Label:
halign: 'left'
valign: 'middle'
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
text: root.text_selected
<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 SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
pass
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]))
rv.name_selected = rv.data[index]['text']
else:
print("selection removed for {0}".format(rv.data[index]))
class CultureView(RecycleView):
def __init__(self, **kwargs):
super(CultureView, self).__init__(**kwargs)
self.data = [
{"text": "Test1", "description": "testu"},
{"text": "Test2", "description": "testo"}
]
class CultureSubView(RecycleView):
planet_selected = StringProperty('')
def __init__(self, **kwargs):
super(CultureSubView, self).__init__(**kwargs)
self.selection_data = {
'': [],
'Test1': [
{"text": "test1.1", "description": "test1"},
{"text": "test1.2", "description": "text1"}
],
'Test2': [
{"text": "test2.1", "description": "text2"},
{"text": "test2.2", "description": "test2"}
]
}
self.data = self.selection_data[self.planet_selected]
def update(self):
print("Updating")
self.data = self.selection_data[self.planet_selected]
self.refresh_from_data()
class CultureLabel(ScrollView):
text_selected = StringProperty('')
name_selected = StringProperty('')
class ScreenCulture(Screen):
pass
screen_manager = ScreenManager()
screen_manager.add_widget(ScreenCulture(name="screen_culture"))
class TestApp(App):
def build(self):
return screen_manager
if __name__ == "__main__":
TestApp().run()
一如既往,感谢您的帮助:)
解决方案
由于该项目是SelectableLabel,因此使用on_touch_down事件来调用方法CultureSubView.update()。
调用方法CultureSubView.update()有两种选择,一种来自 kv 文件,另一种来自 Python 脚本。两个选项都使用了 Kivy ObjectProperty。添加ObjectProperty以连接culture_sub_view、ScreenManager和ScreenCulture。详情请参阅示例。
选项 1 -通过 kv 文件调用CultureSubView.update()
在这个选项中,on_touch_down事件被调用了两次,因为我们有一个类 SelectableLabel,它在两个地方使用,即 CultureView 和 CultureSubView。
片段
.kv 文件
Builder.load_string('''
<ScreenManagement>:
screen_culture: screen_culture
ScreenCulture:
id: screen_culture
name: 'screen_culture'
<ScreenCulture>:
culture_sub_view: culture_sub_view
...
<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
on_touch_down:
print('on_touch_down:')
if self.selectable: \
app.root.screen_culture.culture_sub_view.update(self.text)
Python 脚本
class SelectableLabel(RecycleDataViewBehavior, Label):
...
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)
...
class ScreenCulture(Screen):
culture_sub_view = ObjectProperty(None)
class ScreenManagement(ScreenManager):
screen_culture = ObjectProperty(None)
class TestApp(App):
def build(self):
return ScreenManagement()
选项 2 -通过 Python 脚本调用CultureSubView.update()
在这个选项中,我们使用App.get_running_app().root.screen_culture.culture_sub_view.update()调用该方法并将self.text传递给它。
片段
.kv 文件
Builder.load_string('''
<ScreenManagement>:
screen_culture: screen_culture
ScreenCulture:
id: screen_culture
name: 'screen_culture'
<ScreenCulture>:
culture_sub_view: culture_sub_view
Python 脚本
class SelectableLabel(RecycleDataViewBehavior, Label):
...
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:
App.get_running_app().root.screen_culture.culture_sub_view.update(self.text)
return self.parent.select_with_touch(self.index, touch)
...
class ScreenCulture(Screen):
culture_sub_view = ObjectProperty(None)
class ScreenManagement(ScreenManager):
screen_culture = ObjectProperty(None)
class TestApp(App):
def build(self):
return ScreenManagement()
例子
选项 1 -通过 kv 文件调用CultureSubView.update()
from kivy.app import App
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.lang import Builder
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
from kivy.uix.scrollview import ScrollView
Builder.load_string('''
<ScreenManagement>:
screen_culture: screen_culture
ScreenCulture:
id: screen_culture
name: 'screen_culture'
<ScreenCulture>:
culture_sub_view: culture_sub_view
BoxLayout:
orientation: 'vertical'
Label:
pos_hint: {"x": .45, "top": 1}
text: "Testosterone"
size_hint: .1, .1
GridLayout:
id: culture_layout
rows: 1
cols: 3
padding: dp(10)
spacing: dp(10)
orientation: 'horizontal'
CultureView:
id: culture_list_view
CultureSubView:
id: culture_sub_view
name_selected:
"Planet" if not culture_list_view.name_selected else culture_list_view.name_selected
CultureLabel:
id: culture_text
name_selected:
"NVM" if not culture_sub_view.name_selected else culture_sub_view.name_selected
text_selected:
"This is totally a test text" if not culture_sub_view.text_selected else culture_sub_view.text_selected
<CultureView>:
viewclass: 'SelectableLabel'
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureSubView>:
viewclass: 'SelectableLabel'
text_selected: ''
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureLabel>:
size_hint_y: .85
Label:
halign: 'left'
valign: 'middle'
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
text: root.text_selected
<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
on_touch_down:
print('on_touch_down:')
if self.selectable: \
app.root.screen_culture.culture_sub_view.update(self.text)
''')
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
pass
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]))
rv.name_selected = rv.data[index]['text']
else:
print("selection removed for {0}".format(rv.data[index]))
class CultureView(RecycleView):
def __init__(self, **kwargs):
super(CultureView, self).__init__(**kwargs)
self.data = [
{"text": "Test1", "description": "testu"},
{"text": "Test2", "description": "testo"}
]
class CultureSubView(RecycleView):
planet_selected = StringProperty('')
def __init__(self, **kwargs):
super(CultureSubView, self).__init__(**kwargs)
self.selection_data = {
'': [],
'Test1': [
{"text": "test1.1", "description": "test1"},
{"text": "test1.2", "description": "text1"}
],
'Test2': [
{"text": "test2.1", "description": "text2"},
{"text": "test2.2", "description": "test2"}
]
}
self.data = self.selection_data[self.planet_selected]
def update(self, name_selected):
print("Updating")
self.planet_selected = name_selected
self.data = self.selection_data[self.planet_selected]
self.refresh_from_data()
class CultureLabel(ScrollView):
text_selected = StringProperty('')
name_selected = StringProperty('')
class ScreenCulture(Screen):
culture_sub_view = ObjectProperty(None)
class ScreenManagement(ScreenManager):
screen_culture = ObjectProperty(None)
class TestApp(App):
def build(self):
return ScreenManagement()
if __name__ == "__main__":
TestApp().run()
选项 2 -通过 Python 脚本调用CultureSubView.update()
from kivy.app import App
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.lang import Builder
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
from kivy.uix.scrollview import ScrollView
Builder.load_string('''
<ScreenManagement>:
screen_culture: screen_culture
ScreenCulture:
id: screen_culture
name: 'screen_culture'
<ScreenCulture>:
culture_sub_view: culture_sub_view
BoxLayout:
orientation: 'vertical'
Label:
pos_hint: {"x": .45, "top": 1}
text: "Testosterone"
size_hint: .1, .1
GridLayout:
id: culture_layout
rows: 1
cols: 3
padding: dp(10)
spacing: dp(10)
orientation: 'horizontal'
CultureView:
id: culture_list_view
CultureSubView:
id: culture_sub_view
name_selected:
"Planet" if not culture_list_view.name_selected else culture_list_view.name_selected
CultureLabel:
id: culture_text
name_selected:
"NVM" if not culture_sub_view.name_selected else culture_sub_view.name_selected
text_selected:
"This is totally a test text" if not culture_sub_view.text_selected else culture_sub_view.text_selected
<CultureView>:
viewclass: 'SelectableLabel'
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureSubView>:
viewclass: 'SelectableLabel'
text_selected: ''
name_selected: ''
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<CultureLabel>:
size_hint_y: .85
Label:
halign: 'left'
valign: 'middle'
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
text: root.text_selected
<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 SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
pass
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:
App.get_running_app().root.screen_culture.culture_sub_view.update(self.text)
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]))
rv.name_selected = rv.data[index]['text']
else:
print("selection removed for {0}".format(rv.data[index]))
class CultureView(RecycleView):
def __init__(self, **kwargs):
super(CultureView, self).__init__(**kwargs)
self.data = [
{"text": "Test1", "description": "testu"},
{"text": "Test2", "description": "testo"}
]
class CultureSubView(RecycleView):
planet_selected = StringProperty('')
def __init__(self, **kwargs):
super(CultureSubView, self).__init__(**kwargs)
self.selection_data = {
'': [],
'Test1': [
{"text": "test1.1", "description": "test1"},
{"text": "test1.2", "description": "text1"}
],
'Test2': [
{"text": "test2.1", "description": "text2"},
{"text": "test2.2", "description": "test2"}
]
}
self.data = self.selection_data[self.planet_selected]
def update(self, name_selected):
print("Updating")
self.planet_selected = name_selected
self.data = self.selection_data[self.planet_selected]
self.refresh_from_data()
class CultureLabel(ScrollView):
text_selected = StringProperty('')
name_selected = StringProperty('')
class ScreenCulture(Screen):
culture_sub_view = ObjectProperty(None)
class ScreenManagement(ScreenManager):
screen_culture = ObjectProperty(None)
class TestApp(App):
def build(self):
return ScreenManagement()
if __name__ == "__main__":
TestApp().run()
输出:选项 1 -通过 kv 文件调用CultureSubView.update()
输出:选项 2 -通过 Python 脚本调用CultureSubView.update()
推荐阅读
- r - 按一列匹配两个数据框并从R中另一列中的匹配行中减去
- html - 悬停时的图像与粘性标题重叠
- python - 如何在 django 的数据库中显示主页中的视频
- javascript - 如何将值四舍五入到小数点后 1 位?
- django - 视图中的 Django 模型对象访问
- wordpress - WordPress ACF 插件到 Rest API
- android - 我如何自定义 JsonObjectRequest 以便我可以覆盖 volley 库中的 getParams 方法
- xpath - 无法使用 xpath 中的文本定位元素
- forms - 集合字段的 FileType 倍数
- javascript - 选择不起作用 - 单击时未出现选项