Kivy ScrollView и ScreenManager: как обработать значение чрезмерной прокрутки и вызвать событие на главном экранеPython

Программы на Python
Ответить
Anonymous
 Kivy ScrollView и ScreenManager: как обработать значение чрезмерной прокрутки и вызвать событие на главном экране

Сообщение Anonymous »

Во-первых, программирование для меня — хобби, а не профессия. В приведенном ниже примере кода создаются некоторые искусственные данные в словаре, к которым я хочу получить доступ по ключу, когда контейнер ScrollView прокручивается слишком сильно. Я уже несколько дней пытаюсь найти решение... играю с декораторами и ищу подобные проблемы в сети, но безуспешно. Я использую Python 3.14.1 в Linux с Kivy 2.3.1.
Пример main.kv

Код: Выделить всё

#: import Effect main.Effect

ManagerWidget:
StartScreen:
Page2Screen:

:
name: 'startscreen'

BoxLayout:
orientation: 'vertical'

canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size

BoxLayout:
size_hint_y: .1

Button:
id: btn1
text: 'Simulation of desired "prev_key" function via overscroll event'
on_release: root.prev_key ( )

Button:
id: btn2
text: 'Simulation of desired "next_key" function via overscroll event'
on_release: root.next_key ( )

ScrollView:
id: scroller
effect_cls: Effect
size_hint: 1, 1
do_scroll_x: False
GridLayout:
id: container
cols: 5
spacing: 2
size_hint_y: None
height: self.minimum_height

BoxLayout:
size_hint_y: .1

Button:
text: 'Go to Page 2'
on_release: root.manager.current = 'page2'

:
name: 'page2'
BoxLayout:
padding: 5
spacing: 5
orientation: 'vertical'

Label:
text: 'Placeholder 1'
Label:
text: 'Placeholder 2'
Label:
text: 'Placeholder 3'

BoxLayout:
size_hint_y: .3
Button:
text: 'Back to main screen'
on_release:
root.manager.current = 'startscreen'
И main.py

Код: Выделить всё

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput

from kivy.effects.dampedscroll import DampedScrollEffect
from kivy.metrics import dp
from kivy.clock import Clock

from time import time

class CallControl:

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 __init__ ( self, *args, **kwargs ):
super ( Effect, self ).__init__ ( **kwargs )

def on_overscroll ( self, *args ):
self.args = args

if self.overscroll < -100:
self.scrollup ( )

elif self.overscroll > 100:
self.scrolldown ( )

@CallControl ( max_call_interval = 1 )
def scrollup ( self ):
print ( 'How to update the Scrollview widgets? (i.e. the prev_key method in StartScreen )' )
# StartScreen.prev_key ( self.overscroll ) ???

@CallControl ( max_call_interval = 1 )
def scrolldown ( self ):
print ( 'How to update the Scrollview widgets? (i.e.  the next_key method in StartScreen )' )
# StartScreen.next_key ( self.overscroll ) ???

class StartScreen ( Screen ):

def __init__ ( self, **kwargs ):
super( StartScreen, self).__init__( **kwargs )

# Create some artificial data for this sample code to fill the GridLayout container
self.num    = '11'
self.data   = { }
self.keys   = [ ]
lines       = [ ]
for k in range ( 10, 15 ):

for v in range ( 25 ):
lines.append ( 'ONE,Key %d,%d,yxz,,white,gray,yellow,red,green,\n' % ( k, k+v ) )

self.data[ str ( k ) ] = lines
self.keys.append ( str ( k ) )
lines = [ ]

self.colour_mapping = { 'white'     : ( 1,1,1,1, ),
'gray'      : ( 0,0,0,.2 ),
'green'     : ( 0,1,0,.3 ),
'red'       : ( 1,0,0,.3 ),
'yellow'    : ( 1,1,0,.3 ) }

Clock.schedule_once ( self.finish_init, 0 )

def finish_init ( self, dt ):
self.update_container ( )

# @classmethod ? But how to call self.update_container then? And the keys list is empty anyway... hmpf...
def prev_key ( self, *args ):
idx = self.keys.index ( self.num )

if idx in ( 0, len ( self.keys ) ):
print ( 'no more keys in the dict...' )
self.num = self.keys[ idx ]

else:
self.num = self.keys[ idx - 1 ]

self.update_container ( )

def next_key ( self, *args ):
idx = self.keys.index ( self.num )

try:
self.num = self.keys[ idx + 1 ]

except IndexError:
print ( 'no more keys in the dict...' )
self.num = self.keys[ idx ]

self.update_container ( )

def update_container ( self ):

hgt_row     = 35
fnt_size    = 15

self.ids.container.clear_widgets ( )

for line in self.data.get ( self.num ):

d1, d2, d3, d4, empty, bg1,bg2,bg3,bg4,bg5, nl = line.split( ',' )[ : ]

colour1 = self.colour_mapping.get ( bg1 )
colour2 = self.colour_mapping.get ( bg2 )
colour3 = self.colour_mapping.get ( bg3 )
colour4 = self.colour_mapping.get ( bg4 )
colour5 = self.colour_mapping.get ( bg5 )

in_c1 = TextInput ( height              = hgt_row,\
text                = d1,\
font_size           = dp ( fnt_size ),\
size_hint           = ( .1, None ),\
background_color    = colour1 )

in_c2 = TextInput ( height              = hgt_row,\
text                = d2,\
font_size           = dp ( fnt_size ),\
size_hint           = ( .12, None ),\
background_color    = colour2 )

in_c3 = TextInput ( height              = hgt_row,\
text                = d3,\
size_hint           = ( .07, None ),\
background_color    = colour3 )

in_c4 = TextInput ( height              = hgt_row,\
size_hint           = ( .09, None ),\
text                = d4,\
background_color    = colour4 )

in_c5 = TextInput ( height              = hgt_row,\
size_hint           = ( .7, None ),\
hint_text           = empty,\
background_color    = colour5 )

self.ids.container.add_widget ( in_c1 )
self.ids.container.add_widget ( in_c2 )
self.ids.container.add_widget ( in_c3 )
self.ids.container.add_widget ( in_c4 )
self.ids.container.add_widget ( in_c5 )

class Page2Screen ( Screen ):
pass

class ManagerWidget ( ScreenManager ):
pass

class MainApp ( App ):
pass

if __name__ == '__main__':
MainApp( ).run( )
Что мне здесь не хватает? Есть предложения?
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»