我有一个ScrollView
,当您过度滚动到顶部时(例如在许多应用中),它应该具有更新功能。我已经找到了一种在过度滚动超过某个阈值时触发它的方法,但它会多次触发它,因为每次移动都会触发on_overscroll
事件。那么有限制它的方法吗?
我的代码如下所示:
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.effects.dampedscroll import DampedScrollEffect
class Effect(DampedScrollEffect):
def on_overscroll(self, *args):
super().on_overscroll(*args)
if self.overscroll < -50:
print('hey')
class TestApp(App):
def build(self):
sv = ScrollView(effect_cls = Effect,
size_hint_y = 0.2)
gl = GridLayout(cols = 1,
size_hint_y = None)
gl.bind(minimum_height = gl.setter('height'))
for i in range(5):
gl.add_widget(Button(text = str(i),
size_hint = (None, None)))
sv.add_widget(gl)
return sv
TestApp().run()
因此,正如您所看到的,当过度滚动超过50时,它会打印一条简单的消息。但是当你真正尝试它时,你会发现它打印了很多次。我想要的是触发一个事件,在一段时间内(例如一秒钟)保持不可触发并更新内容。我已经尝试过使用布尔标志和Clock
,但它没有用。在这可以做些什么?
答案 0 :(得分:2)
我会在这里使用有状态的装饰器:
class call_control:
def __init__(self, max_call_interval):
self._max_call_interval = max_call_interval
self._last_call = time()
def __call__(self, function):
def wrapped(*args, **kwargs):
now = time()
if now - self._last_call > self._max_call_interval:
self._last_call = now
function(*args, **kwargs)
return wrapped
class Effect(DampedScrollEffect):
def on_overscroll(self, *args):
super().on_overscroll(*args)
if self.overscroll < -50:
self.do_something()
@call_control(max_call_interval=1)
def do_something(self):
print('hey')
答案 1 :(得分:0)
我知道这是一个老问题,但有人可能会觉得有用 这是来自tshirtman的github gist的示例
from threading import Thread
from time import sleep
from kivy.app import App
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.clock import mainthread
from kivy.properties import ListProperty, BooleanProperty
KV = '''
FloatLayout:
Label:
opacity: 1 if app.refreshing or rv.scroll_y > 1 else 0
size_hint_y: None
pos_hint: {'top': 1}
text: 'Refreshing…' if app.refreshing else 'Pull down to refresh'
RecycleView:
id: rv
data: app.data
viewclass: 'Row'
do_scroll_y: True
do_scroll_x: False
on_scroll_y: app.check_pull_refresh(self, grid)
RecycleGridLayout:
id: grid
cols: 1
size_hint_y: None
height: self.minimum_height
default_size: 0, 36
default_size_hint: 1, None
<Row@Label>:
_id: 0
text: ''
canvas:
Line:
rectangle: self.pos + self.size
width: 0.6
'''
class Application(App):
data = ListProperty([])
refreshing = BooleanProperty()
def build(self):
self.refresh_data()
return Builder.load_string(KV)
def check_pull_refresh(self, view, grid):
max_pixel = 200
to_relative = max_pixel / (grid.height - view.height)
if view.scroll_y < 1.0 + to_relative or self.refreshing:
return
self.refresh_data()
def refresh_data(self):
Thread(target=self._refresh_data).start()
def _refresh_data(self):
self.refreshing = True
sleep(2)
self.append_data([
{'_id': i, 'text': 'hello {}'.format(i)}
for i in range(len(self.data), len(self.data) + 50)
])
self.refreshing = False
@mainthread
def append_data(self, data):
self.data = self.data + data
if __name__ == "__main__":
Application().run()