gpt4 book ai didi

python - 如何在每次数据变化时刷新kivy RecycleView?

转载 作者:太空宇宙 更新时间:2023-11-03 14:08:08 29 4
gpt4 key购买 nike

我正在尝试创建一个简单的考勤应用程序。

程序启动时,所有标签都在取消选择列表中

预期行为:选择任何标签时,数据将移动到所选列表,现在所选标签位于连接列表的末尾。然后 RecycleView 刷新以显示此更改。

所以我设法使数据从一个列表移动到另一个列表,但我无法使 RecycleView 刷新

我尝试使用 ids 但失败了

我希望有人能帮助我。我认为这对于有知识的人来说是一个常规问题,但对于像我这样的菜鸟来说却不是。

我是第一次在这个网站上提问,所以提前抱歉

这是代码:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
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.properties import ListProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from datetime import datetime
import kivy
from kivy.config import Config
Config.set('graphics', 'width', '300')
Config.set('graphics', 'height', '500')

importedlist = ['Novella Varela', 'Caroll Faircloth', 'Douglas Schissler',
'Rolande Hassell', 'Hayley Rivero', 'Niesha Dungy', 'Winfred Dejonge', 'Venetta Milum']
deselected_list = importedlist[:]
selected_list = []

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.
and add/remove items from lists
'''
self.selected = is_selected
if self.selected and self.text in deselected_list:
selected_list.append(self.text)
deselected_list.remove(self.text)
print(selected_list)
elif not self.selected and self.text in selected_list:
deselected_list.append(self.text)
selected_list.remove(self.text)
print(deselected_list)

class RV(RecycleView):
# this needs to be updated every time any label is selected or deselected
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = ([{'text': str(row)} for row in sorted(deselected_list)]
+ [{'text': str(row)} for row in sorted(selected_list)])

class Screen(BoxLayout):
now = datetime.now()

def nowdate(self):
return self.now.strftime('%d')

def nowmonth(self):
return self.now.strftime('%m')

def nowyear(self):
return self.now.strftime('%y')

def nowhour(self):
return self.now.strftime('%H')

def nowminute(self):
return self.now.strftime('%M')

Builder.load_string('''
#:import datetime datetime

<Screen>:
orientation: 'vertical'
BoxLayout:
size_hint_y: None
height: 30
TextInput:
id: date
text: root.nowdate()
TextInput:
id: date
text: root.nowmonth()
TextInput:
id: date
text: root.nowyear()
TextInput:
id: date
text: root.nowhour()
TextInput:
id: date
text: root.nowminute()
Button:
RV:
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: None, dp(45)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Button:
size_hint_y: None
height: 30

<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

''')

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

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

最佳答案

好吧,我确实在尝试解决这个问题时绊倒了几次,但我想我已经明白了。我所做的是创建两个回收 View 和一个可以访问 ButtonBehaviors 的 CustomLabel,以便您可以使用“on_press”而不是“on_touch_down”(它在整个树中传播,而不是与元素交互)。

Example Video

py文件:

from kivy.app import App
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.floatlayout import FloatLayout

# Create a Custom ButtonLabel that can use on_press
class ButtonLabel(ButtonBehavior, Label):

# App.get_running_app() lets us traverse all the way through our app from
# the very top, which allows us access to any id. In this case we are accessing
# the content of our selected_list_view of our app
@property
def selected_list_content(self):
return App.get_running_app().root.ids.selected_list.ids.content

# And in this case, we're accessing the content of our deselected_list_view
@property
def deselected_list_content(self):
return App.get_running_app().root.ids.deselected_list.ids.content

# This is our callback that our Label's will call when pressed
def change_location(self):

# If the label's parent is equal* the selected list, we remove the label from its
# parent, and then we add it to the other list
if self.parent == self.selected_list_content:
self.parent.remove_widget(self)
self.deselected_list_content.add_widget(self)

# If the label's parent is not the selected list, then it is the deselected list
# so we remove it from its parent and add it to the selected list
else:
self.parent.remove_widget(self)
self.selected_list_content.add_widget(self)

#* Note: Kivy uses weak references. This is why we use ==, and not 'is'

# We create a CustomRecycleView that we will define in our kv file
class CustomRecycleView(RecycleView):
pass

class MainWindow(FloatLayout):
pass

class ExampleApp(App):

def build(self):
# We create an instance of the MainWindow class, so we can access its id
# to import our list. Otherwise we would have nothing to add the list too
main_window = MainWindow()
importedlist = ['Novella Varela', 'Caroll Faircloth', 'Douglas Schissler',
'Rolande Hassell', 'Hayley Rivero', 'Niesha Dungy', 'Winfred Dejonge', 'Venetta Milum']

# We create a Label for each Name in our imported list, and then add it
# to the content of selected list as a default
# I'm sure you'll be importing our own lists in a different manner
# This is just for the example
for name in importedlist:
NameLabel = ButtonLabel(text=(name))
main_window.ids.selected_list.ids.content.add_widget(NameLabel)
return main_window

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

kv 文件:

#:kivy 1.10.0

# We create a reference to the ButtonLabel class in our py file
<ButtonLabel>:
# We add our callback to our ButtonLabels on press event, on_press
on_press: root.change_location()

# We create a reference to our CustomRecycleView class in our py file
<CustomRecycleView>:
# We create a GridLayout to store all of the content in our RecycleView
GridLayout:
# We give it the id content so we can define the two property values in
# ButtonLabel class in the py file
id: content
size_hint_y: None

# One column because we want it to be vertical list list
cols: 1

# This set up, as well as size_hint_y set to None
# is so we can scroll vertically without issue
row_default_height: 60
height: self.minimum_height

<MainWindow>:
# We then create two instances of our CustomRecycleView, give them the ids
# referenced by the ButtonLabel methods as well as give them equal share of the
# screen space so they do not step on each others toes
# The canvas here is just for prototyping purposes to make sure they are the
# properly defined sizes. You can do whatever with them you would like tbh.
CustomRecycleView:
id: selected_list
size_hint: 1, .5
pos_hint: {'x': 0, 'y': .5}
canvas:
Color:
rgba: 100, 0, 0, .2
Rectangle:
size: self.size
pos: self.pos
CustomRecycleView:
id: deselected_list
size_hint: 1, .45
canvas:
Color:
rgba: 0, 0, 100, .2
Rectangle:
size: self.size
pos: self.pos

关于python - 如何在每次数据变化时刷新kivy RecycleView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48714587/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com