Kivy:刷卡(Carousel& ScreenManager)

时间:2015-06-19 09:21:04

标签: kivy

我在ScreenManager中有两个屏幕,它们都包含ScrollView中的许多按钮。这个想法是通过单击按钮向前迈出一步(右)。然后向后退(向左)。所以我试图添加一个Carousel来实现第二页上的一次滑动。这就是我的尝试:

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

3 个答案:

答案 0 :(得分:9)

您可以使用 ScreenManager 手势来完成此操作。 (../ kivy /示例/手势/)

请参阅此处kivy-github-gestures

我在评论代码中解释了所有内容。

首先,您需要创建一个名为gesture_box.py的新Python文件。

gesture_strings copy from here

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的输出将是。此

(&#39;手势表示:&#39 ;,&#39; eNq1WMtSHEcQvM + PiIs36t3dP4CujuADHFhsACEZNmBlW3 / vnOrZxyCWmYPFQQu5OdlVldXVPbp6 / Pr494 / N / FZ1 // 1lO3yePnc0XN3teLj59HT71 / bTsBP8ig8dXm8 + ve5fnr9uX / GnDVffdj5cvStyk7RhF6NUwfO758en / fhYHR9rFx77fWQNO + 4RjCH8wCMsw / VvtCFhZWuspJXZfQzn3 / FrHa5pE6WIca0NH00agv3z9uNFLBfx4f6i / v0krRKspZE7PnyFdKbNZYU0mykjZo3mXlZI15Ruy9Lu4ZWKSiFi9bIoLVl14RXSHI3xHQuLqyxHLZLS + iuk00ZZYaMFmqOYYAEn5hUFSRtlhY0mptZQ6mJsXpeV00Vp / 7 + ypom6wkQ0dEGRpXqgtW250pom6goT1biQRWth0Ddflk4T9cxErkSNpTRG3vVcm4TUpVR2GMoUy + Jpo57ZyFZI1aCOddjbSV0CO9FRkohCpdQVoaeV2n6NuqWddmYntWIW4UwmCvtO4oLODlPn0qyYy7J4GmpnhhKer7W0VkngXZSjOjdz9EtwiBf3FZ1o6amdeYrKQJdEGmae1ob9dZQPTEGBtw0UjMIV8umqTa6mehXEJVVauHLBpDyqq1NDsZpiZUeSy + rpqrWTulqphuHfEGr4eL4cxJmbSyiaEt5ili + Ke5rqfBLHucKKbega3BqdxOlNx7Rl8TTV9SQeCFwCa3hg59ip6KRNMGSDYLhSkxWRp6fua8Q5qFoNDC / sVCq8LJ6OelkU76MHuhHaGrQxJJa73dNSb6vkrWrBNrJWYSm226J6pKdx8pSxU4nMEaIX8jPtWsmKRuAfzMm2bGmkpXGyFIeXoZmrEKaukcpJnXGhaAptw4hwXZ4wkZaGrxJHw1QMN6 / NcBtaUZW0NMoqcVyCzDB9WA0jhpYdjXQ02nLNhfAnYEyBEAzmRemS dhZe0yzYobhnRcMSaEpaHi4l / Sy6uP9HcVw + MXQKegYt4ysiTz + LL8 / FUb1h7uJ72KoYYHkHGC / 5X16226fjlb3EeGcvZbi6xiStGxqug6E87HelDreJ2gxtHTU5Ryt1VGYKlTtKM4UqiSLoGaodtbmCdZTnXE + UY64bHaWYoSVR8rlC5oazcAZmam3ObJkZfNu085 + RYJ2QSWKM96dqBzPHSl1fJmamiNteBydmZoiZkaBOzEywUI9EwTz74ZGQucYkZVOomWpYlzJ + EzEImXUP / H1CVsDrpNCDwc5LdOqOI5p54x4 / RzNx5zdoZo53tzmaqeNSMEczd3OfR2fDlNlIyeztsHSd0EzfpqWdfioaU + ZvRJcZWQCtlzU4i6HlsgZnYXRqiHcZ0hkfaGTB1D5gZPFUP2BkIVXmVeKsnR564IBm7XTaOkc06yXTLjmiWSOpc1SoozRHsxYyVevgn2T + uDHP0cxZfN4kknmKzVtSvKPz1pHMTdTmaOnom3Yv55SeqLQPKD1rKe9Qft5ImHmd7ivpvU7joDj / 0Uv0XkChlfReWa4r6b3kl8cEzoTOoMuMbsW01aYBxdqH8WEOHNB + 0Eyt8860w90kGSUuMqwfQNOJMI1RvF8m6jFH + wE0bb8j2g + g6fw5oqhFPzgfto / 3D / VX / 6Tw3nNtbzYctiM4 / zze7R + SEsN4ao0rAN4 / f9u + 3D592eZXJd8sRnw65f / YvTzfff / StetwrRu8huCVAFT0PS484 + V98x / WYONd&#39;) (&#39; cross:&#39;, - 1.2199187170964643) (&#39;检查:&#39;, - 2.052277818300959) (&#39;圈:&#39;,0.4973932910874005) (&#39; square:&#39;,0.2907537534396739)

那就是它,你有你的字符串:D

答案 1 :(得分:1)

正如您在评论中提到的那样。

  

我有很多页面。每个页面都有一堆按钮。一些   页面上的按钮比屏幕上的按钮多,所以它们需要   滚动的。

现在,Scrollable部分,你已经想通了。(你也可以在kivy文件中做到),See here。您可以在下面的代码中轻松添加它。

  

点击按钮可以带您到下一个孩子   屏幕(具有滚动效果)。任何孩子都应该可以   通过向后滑回到它的父母那里。

此处(下面的代码)您可以滑动或点击按钮进行导航。

现在,

  

鉴于我将有很多页面,我可能需要Carousel   使用add_widget()和remove_widget()动态加载。

这些例子对您有所帮助。 Kivy-ShowcaseContainer

在kivy-showcase中查看load_screen方法以及build函数

以下是点击按钮时add_widgets的示例

Builder.load_string('''
[SideBar@BoxLayout]:
    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:

问:如何使用load_slide()方法?

load_slide()方法将幻灯片作为参数def load_slide(self, slide):

问:那么现在如何获得幻灯片?。

slide是列表属性slides = ListProperty([])

在按钮包含文字"go back (3)"

的位置打印

on_release: print( self.parent.parent.parent.parent.parent.ids.carousel.slides) 您将获得id(carousel)下所有幻灯片的列表。

这就是你如何使用它。  .....ids.carousel.load_slide(....ids.carousel..slides[2])

答案 2 :(得分:0)

我有另一种可以使用的方法。它不是通过Carousel,而是允许您通过滑动来更改屏幕。您可以创建一个方法,该方法将屏幕的初始接触点的x点和屏幕的最终接触点的x点相减。这是视频的链接(https://www.youtube.com/watch?v=8pqtMAUEUyo&t=65s

    def on_touch_move(self, touch):
        if touch.ox - touch.x > 50:  # check for swiping gestures
            # ScreenManger change screen

touch.ox是屏幕(x轴)的初始接触点,touch.x是最终的接触点。如果差异大于设定值,则会更改屏幕。