Python Kivy。如何更改Pagelayout的方向?

时间:2018-08-13 21:38:33

标签: python kivy

我需要将方向更改为垂直方向,但其工作方式与BoxLayout不同。 Kivy官方文档中也没有关于此的信息。此外,是否可以通过从屏幕上的任意位置(不仅是边框)滑动来更改页面?

Python:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

class MainScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

presentation = Builder.load_file("final.kv")

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

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

基维:

ScreenManagement:
    MainScreen:

<MainScreen>:
    canvas:
        Rectangle:
            source: "nakedman.jpg"
            pos: self.pos
            size: self.size

    name: "main"

    PageLayout:
        orientation: "vertical"
        BoxLayout:
            Button:
                text: "Button1"
            Button:
                text: "Button2"
        BoxLayout:
            Button:
                text: "Button3"
            Button:
                text: "Button4"     

1 个答案:

答案 0 :(得分:0)

PageLayout没有方向属性,因此您必须构建所有内容,在这种情况下,请使用source code of PageLayout获得以下新代码:

__all__ = ('PageLayoutVertical', )

from kivy.uix.layout import Layout
from kivy.properties import NumericProperty, DictProperty
from kivy.animation import Animation


class PageLayoutVertical(Layout):
    '''PageLayout class. See module documentation for more information.
    '''

    page = NumericProperty(0)
    '''The currently displayed page.
    :data:`page` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 0.
    '''

    border = NumericProperty('50dp')
    '''The width of the border around the current page used to display
    the previous/next page swipe areas when needed.
    :data:`border` is a :class:`~kivy.properties.NumericProperty` and
    defaults to 50dp.
    '''

    swipe_threshold = NumericProperty(.5)
    '''The thresold used to trigger swipes as percentage of the widget
    size.
    :data:`swipe_threshold` is a :class:`~kivy.properties.NumericProperty`
    and defaults to .5.
    '''

    anim_kwargs = DictProperty({'d': .5, 't': 'in_quad'})
    '''The animation kwargs used to construct the animation
    :data:`anim_kwargs` is a :class:`~kivy.properties.DictProperty`
    and defaults to {'d': .5, 't': 'in_quad'}.
    .. versionadded:: 1.11.0
    '''

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

        trigger = self._trigger_layout
        fbind = self.fbind
        fbind('border', trigger)
        fbind('page', trigger)
        fbind('parent', trigger)
        fbind('children', trigger)
        fbind('size', trigger)
        fbind('pos', trigger)

    def do_layout(self, *largs):
        l_children = len(self.children) - 1
        w = self.width
        x_parent, y_parent = self.pos
        p = self.page
        border = self.border
        half_border = border / 2.
        top = self.top
        height = self.height - border
        for i, c in enumerate(reversed(self.children)):

            if i < p:
                y = y_parent
            elif i == p:
                if not p:  # it's first page
                    y = y_parent
                elif p != l_children:  # not first, but there are post pages
                    y = y_parent + half_border
                else:  # not first and there are no post pages
                    y = y_parent + border
            elif i == p + 1:
                if not p:  # second page - no left margin
                    y = top - border
                else:  # there's already a left margin
                    y = top - half_border
            else:
                y = top

            c.width = w
            c.height = height

            Animation(
                x=x_parent,
                y=y,
                **self.anim_kwargs).start(c)

    def on_touch_down(self, touch):
        if (
            self.disabled or
            not self.collide_point(*touch.pos) or
            not self.children
        ):
            return

        page = self.children[-self.page - 1]
        if self.y <= touch.y < page.y:
            touch.ud['page'] = 'previous'
            touch.grab(self)
            return True
        elif page.top <= touch.y < self.top:
            touch.ud['page'] = 'next'
            touch.grab(self)
            return True
        return page.on_touch_down(touch)

    def on_touch_move(self, touch):
        if touch.grab_current != self:
            return

        p = self.page
        border = self.border
        half_border = border / 2.
        page = self.children[-p - 1]
        if touch.ud['page'] == 'previous':
            # move next page upto right edge
            if p < len(self.children) - 1:
                self.children[-p - 2].y = min(
                    self.top - self.border * (1 - (touch.sy - touch.osy)),
                    self.top)

            # move current page until edge hits the right border
            if p >= 1:
                b_right = half_border if p > 1 else border
                b_left = half_border if p < len(self.children) - 1 else border
                self.children[-p - 1].y = max(min(
                    self.y + b_left + (touch.y - touch.oy),
                    self.top - b_right),
                    self.y + b_left)

            # move previous page left edge upto left border
            if p > 1:
                self.children[-p].y = min(
                    self.y + half_border * (touch.sy - touch.osy),
                    self.y + half_border)

        elif touch.ud['page'] == 'next':
            # move current page upto left edge
            if p >= 1:
                self.children[-p - 1].y = max(
                    self.y + half_border * (1 - (touch.osy - touch.sy)),
                    self.y)

            # move next page until its edge hit the left border
            if p < len(self.children) - 1:
                b_right = half_border if p >= 1 else border
                b_left = half_border if p < len(self.children) - 2 else border
                self.children[-p - 2].y = min(max(
                    self.top - b_right + (touch.y - touch.oy),
                    self.y + b_left),
                    self.top - b_right)

            # move second next page upto right border
            if p < len(self.children) - 2:
                self.children[-p - 3].y = max(
                    self.top + half_border * (touch.sy - touch.osy),
                    self.top - half_border)

        return page.on_touch_move(touch)

    def on_touch_up(self, touch):
        if touch.grab_current == self:
            if (
                touch.ud['page'] == 'previous' and
                abs(touch.y - touch.oy) / self.height > self.swipe_threshold
            ):
                self.page -= 1
            elif (
                touch.ud['page'] == 'next' and
                abs(touch.y - touch.oy) / self.height > self.swipe_threshold
            ):
                self.page += 1
            else:
                self._trigger_layout()

            touch.ungrab(self)

        if len(self.children) > 1:
            return self.children[-self.page + 1].on_touch_up(touch)


if __name__ == '__main__':
    from kivy.base import runTouchApp
    from kivy.uix.button import Button

    pl = PageLayoutVertical()
    for i in range(1, 10):
        b = Button(text='page%s' % i)
        pl.add_widget(b)

    runTouchApp(pl)