Kivy: Swiping (Carousel & ScreenManager)

У меня есть два экрана в ScreenManager, который содержит несколько кнопок в ScrollView. Идея состоит в том, что один шаг вперед (справа), нажав кнопку. И отступите назад (слева), откинув назад. Поэтому я пытаюсь добавить карусель, чтобы реализовать эту прокрутку на второй странице. Это то, что я пробовал:

self.root = ScreenManager(id = 'screen_manager')

main_screen = Screen(name = 'main_screen')

scroller = Scroller()
button_text = ['teach', 'move', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8']
for text in button_text:
    scroller.view.add_widget(Field(name=text, direction='left', current='teach'))
main_screen.add_widget(scroller)
self.root.add_widget(main_screen)

carousel = Carousel(direction='left', id='carousel')

teach = Screen(name = 'teach')
scroller2 = Scroller()
button_text = ['vocab', 'drills']
for text in button_text:
    scroller2.view.add_widget(Field(name=text, direction='right', current='main_screen'))
carousel.add_widget(scroller2)
teach.add_widget(carousel)
self.root.add_widget(teach)

Но поскольку я только добавил второй экран, его невозможно прокрутить в любом направлении. Метод карусели load_slide() принимает слайд как аргумент. Предполагая, что слайдом они означают "Карусель". Учитывая, что у меня будет много страниц, мне, вероятно, нужно, чтобы карусель загружалась динамически, используя add_widget() и remove_widget(). Поблагодарили бы некоторых указателей.

Рабочий пример кода, который у меня до сих пор: http://dpaste.com/33464R2

Ответ 1

Вы можете сделать это, используя ScreenManager и Жесты. (../kivy/примеры/жесты/)

Смотрите здесь киви-github-жесты

Я объяснил все в коде в комментариях.

Сначала вам нужно создать новый файл Python с именем gesture_box.py.

gesture_strings копия здесь

from kivy.gesture import GestureDatabase
from kivy.uix.boxlayout import BoxLayout
from kivy.gesture import Gesture 

[Paste gesture_strings here]

#This database can compare gestures the user makes to its stored     gestures 
#and tell us if the user input matches any of them.
gestures = GestureDatabase()
for name, gesture_string in gesture_strings.items():
    gesture = gestures.str_to_gesture(gesture_string)
    gesture.name = name
    gestures.add_gesture(gesture)

class GestureBox(BoxLayout):

    def __init__(self, **kwargs):
        for name in gesture_strings:
            self.register_event_type('on_{}'.format(name))
        super(GestureBox, self).__init__(**kwargs)

    def on_left_to_right_line(self):
        pass

#To recognize a gesture, you’ll need to start recording each individual event in the
#touch_down handler, add the data points for each call to touch_move , and then do the
#gesture calculations when all data points have been received in the touch_up handler.

    def on_touch_down(self, touch):
        #create an user defined variable and add the touch coordinates 
        touch.ud['gesture_path'] = [(touch.x, touch.y)]    
        super(GestureBox, self).on_touch_down(touch)

    def on_touch_move(self, touch):
        touch.ud['gesture_path'].append((touch.x, touch.y))
        super(GestureBox, self).on_touch_move(touch)

    def on_touch_up(self, touch):
        if 'gesture_path' in touch.ud:
            #create a gesture object
            gesture = Gesture()    
            #add the movement coordinates 
            gesture.add_stroke(touch.ud['gesture_path'])
            #normalize so thwu willtolerate size variations
            gesture.normalize()
            #minscore to be attained for a match to be true
            match = gestures.find(gesture, minscore=0.3)
            if match:
                print("{} happened".format(match[1].name))
                self.dispatch('on_{}'.format(match[1].name))
        super(GestureBox, self).on_touch_up(touch)

Теперь создайте файл main.py.

import gesture_box as gesture
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class Runner(gesture.GestureBox):
    pass

class MainApp(App):
    def build(self):
        return Runner()

if __name__ == '__main__':
    app = MainApp()
    app.run()

И ваш файл main.kv

<Runner>:
    #Handling the gesture event.
    on_left_to_right_line: manager.current = 'main_screen';  manager.transition.direction = 'right'
    ScreenManager:
        id: manager
        Screen:
            name: "main_screen"
            BoxLayout:
                orientation: 'vertical'
                Label:
                Button:
                    text: "Child 1"
                    on_release: 
                        manager.current = "child1"
                        manager.transition.direction = 'left'

                Label:
                Button:
                    text: "Child 2"
                    on_release: 
                        manager.current = "child1"
                        manager.transition.direction = 'left'
                Label:

        Screen:
            name: "child1"
            Label:
                text: "Swipe from left to right to go to main screen (CHILD 1)"

        Screen:
            name: "child2"
            Label:
                text: "Swipe from left to right to go to main screen (CHILD 1)"

РЕДАКТИРОВАТЬ: Многие люди спрашивают меня, как генерируется эта строка жестов.

Ребята из Kivy предоставляют это в своих примерах.

см. здесь https://github.com/kivy/kivy/blob/master/examples/gestures/gesture_board.py запустите этот файл.

python gesture_board.py

Он должен открыть пустое окно.

сделайте жест с помощью мыши или касания.

Когда событие on_touch_up запускается, оно выводит строку жестов в терминале.

например, выход для right_to_left_line будет. это

( 'жест представление:', "eNq1WMtSHEcQvM + PiIs36t3dP4CujuADHFhsACEZNmBlW3/vnOrZxyCWmYPFQQu5OdlVldXVPbp6/Pr494/N/fz1//1lO3yePnc0XN3teLj59HT71/bTsBP8ig8dXm8 + ve5fnr9uX/GnDVffdj5cvStyk7RhF6NUwfO758en/fhYHR9rFx77fWQNO + 4RjCH8wCMsw/VvtCFhZWuspJXZfQzn3/FrHa5pE6WIca0NH00agv3z9uNFLBfx4f6i/v0krRKspZE7PnyFdKbNZYU0mykjZo3mXlZI15Ruy9Lu4ZWKSiFi9bIoLVl14RXSHI3xHQuLqyxHLZLS + iuk00ZZYaMFmqOYYAEn5hUFSRtlhY0mptZQ6mJsXpeV00Vp/7 + ypom6wkQ0dEGRpXqgtW250pom6goT1biQRWth0Ddflk4T9cxErkSNpTRG3vVcm4TUpVR2GMoUy + Jpo57ZyFZI1aCOddjbSV0CO9FRkohCpdQVoaeV2n6NuqWddmYntWIW4UwmCvtO4oLODlPn0qyYy7J4GmpnhhKer7W0VkngXZSjOjdz9EtwiBf3FZ1o6amdeYrKQJdEGmae1ob9dZQPTEGBtw0UjMIV8umqTa6mehXEJVVauHLBpDyqq1NDsZpiZUeSy + rpqrWTulqphuHfEGr4eL4cxJmbSyiaEt5ili + Ke5rqfBLHucKKbega3BqdxOlNx7Rl8TTV9SQeCFwCa3hg59ip6KRNMGSDYLhSkxWRp6fua8Q5qFoNDC/sVCq8LJ6OelkU76MHuhHaGrQxJJa73dNSb6vkrWrBNrJWYSm226J6pKdx8pSxU4nMEaIX8jPtWsmKRuAfzMm2bGmkpXGyFIeXoZmrEKaukcpJnXGhaAptw4hwXZ4wkZaGrxJHw1QMN6/NcBtaUZW0NMoqcVyCzDB9WA0jhpYdjXQ02nLNhfAnYEyBEAzmRemSdhZe0yzYobhn RcMSaEpaHi4l/Sy6uP9HcVw + MXQKegYt4ysiTz + LL8/FUb1h7uJ72KoYYHkHGC/5X16226fjlb3EeGcvZbi6xiStGxqug6E87HelDreJ2gxtHTU5Ryt1VGYKlTtKM4UqiSLoGaodtbmCdZTnXE + UY64bHaWYoSVR8rlC5oazcAZmam3ObJkZfNu085 + RYJ2QSWKM96dqBzPHSl1fJmamiNteBydmZoiZkaBOzEywUI9EwTz74ZGQucYkZVOomWpYlzJ + EzEImXUP/H1CVsDrpNCDwc5LdOqOI5p54x4/RzNx5zdoZo53tzmaqeNSMEczd3OfR2fDlNlIyeztsHSd0EzfpqWdfioaU + ZvRJcZWQCtlzU4i6HlsgZnYXRqiHcZ0hkfaGTB1D5gZPFUP2BkIVXmVeKsnR564IBm7XTaOkc06yXTLjmiWSOpc1SoozRHsxYyVevgn2T + uDHP0cxZfN4kknmKzVtSvKPz1pHMTdTmaOnom3Yv55SeqLQPKD1rKe9Qft5ImHmd7ivpvU7joDj/0Uv0XkChlfReWa4r6b3kl8cEzoTOoMuMbsW01aYBxdqH8WEOHNB + 0Eyt8860w90kGSUuMqwfQNOJMI1RvF8m6jFH + wE0bb8j2g + g6fw5oqhFPzgfto/3D/ъх/6Tw3nNtbzYctiM4/zze7R + SEsN4ao0rAN4/f9u + 3D592eZXJd8sRnw65f/YvTzfff/StetwrRu8huCVAFT0PS484 + V98x/WYONd ') ('cross:', -1.2199187170964643) ('check:', -2.052277818300959) ('circle:', 0.4973932910874005) ('square:', 0.2907537534396739)

Что это, у вас есть строка: D

Ответ 2

Как вы просили в своем комментарии.

У меня есть куча страниц. На каждой странице будет множество кнопок. Некоторые страницы имеют больше кнопок, чем могут помещаться на экране, поэтому они должны быть прокручиваются.

Теперь, прокручиваемая часть, вы уже поняли. (Вы также можете сделать это в файле kivy), См. здесь. И вы можете легко добавить это в код ниже.

Нажатие на кнопку приведет вас к следующему ребенку экран (с эффектом прокрутки). На любом ребенке должно быть возможно вернитесь к нему родительским путем, отбросив назад.

Здесь (код ниже) вы можете прокручивать или нажимать кнопки для навигации.

Теперь

Учитывая, что у меня будет много страниц, мне, вероятно, нужна карусель для загружаться динамически, используя add_widget() и remove_widget().

Эти примеры помогут вам. Kivy-Showcase и Container

В киви-витрине посмотрите метод load_screen, а также функцию build

Вот пример add_widgets при нажатии кнопки

Builder.load_string('''
[[email protected]]:
    content: content
    orientation: 'vertical'
    size_hint: .2,1
    BoxLayout:
        orientation: 'vertical'
        # just add a id that can be accessed later on
        id: content

<Root>:
    Button:
        center_x: root.center_x
        text: 'press to add_widgets'
        size_hint: .2, .2
        on_press:
            sb.content.clear_widgets()
            root.load_content(sb.content)
    SideBar:
        id: sb
''')

class Root(BoxLayout):

    def load_content(self, content):
        for but in range(20):
            content.add_widget(Button(text=str(but)))

class MyApp(App):
    def build(self):
        return Root()

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

Вот пример экранов.

Вот файл main.py

from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty

class ShowTime(BoxLayout):
    carousel = ObjectProperty(None)

class Screen1(Screen):
    pass

class Screen2(Screen):
    pass

class MainApp(App):
    def build(self):
         return ShowTime()

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

Вот файл main.kv

<Screen1>:
    name: "screen1"
    BoxLayout:
        orientation: 'vertical'
        padding: 50
        spacing: 50
        Button:
            text: "Next (2)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_next()
        Button:
            text: "Go back (2)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()

<Screen2>:
    name: "screen2"
    BoxLayout:
        orientation: 'vertical'
        padding: 100
        spacing: 100
        Button:
            text: "go back (3)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()

<Showtime>:
    carousel: carousel
    Carousel:
        id: carousel
        loop: True
        BoxLayout:
            padding: 100
            spacing: 100
            Button:
                text: 'Tap me or Swipe (1)'
                on_release: carousel.load_next()
        Screen1:
        Screen2:

РЕДАКТИРОВАТЬ 1:

Q- Как использовать метод load_slide()?

load_slide() принимает слайды как параметр def load_slide(self, slide):

Q- Итак, как получить слайд?.

slide - это свойство списка slides = ListProperty([]),

Распечатайте это, где кнопка имеет текст "go back (3)"

on_release: print( self.parent.parent.parent.parent.parent.ids.carousel.slides) вы получите список всех слайдов под идентификатором (карусель).

Вот как вы его используете.  .....ids.carousel.load_slide(....ids.carousel..slides[2])