在Kivy中如何通过该功能实现向新Screen的过渡?

时间:2018-07-31 19:12:50

标签: python python-3.x kivy kivy-language

我想在单击按钮后实现到新屏幕的过渡,并且我想通过该功能来实现。 我有这个kv代码

<ScreenFrame@BoxLayout>:
    orientation: 'vertical'
    cols: 3

    ActionBar:
        ActionView:
            pos_hint: {'top':1}
            use_separator: True
            ActionPrevious:
                title: "Title"
                with_previous: False
            ActionButton:
                text: "+"


    Label:
        text: "Content"


    BoxLayout:
        orientation: 'horizontal'
        cols: 4
        size_hint: 1, 0.15

        Button:
            text: "Notes"
            #don't work
            on_press: root.manager.current = 'nts'
        Button:
            text: "Docs"
            #don't work
            on_release: root.go_to_dcs()

        Button:
            text: "Videos"
            #don't work
            on_release: root.manager.current = "vds"
        Button:
            text: "Pictures"
            # don't work
            on_release: root.manager.current = 'pctrs'

<NtsScreen>:
    BoxLayout:
        orientation: "vertical"
        cols: 2

        ScreenFrame:
        Button:
            text: "f"
            #work, but me need implementaion through function
            on_press: root.manager.current = "vds"

<DocsScreen>:
    ScreenFrame:

<VdsScreen>:
    ScreenFrame:

<PctrsScreen>:
    ScreenFrame:

和此文件

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.properties import StringProperty
from kivy.uix.widget import Widget


Builder.load_file("main.kv")

class ScreenFrame():
    def go_to_dcs(self):
        sm.current = "dcs"

class NtsScreen(Screen):
    pass

class DcsScreen(Screen):
    def go_to_dcs(self):
        sm.current = 'dcs'

class VdsScreen(Screen):
    pass

class PctrsScreen(Screen):
    pass


# Create the screen manager
sm = ScreenManager()
sm.add_widget(NtsScreen(name='nts'))
sm.add_widget(DcsScreen(name='dcs'))
sm.add_widget(VdsScreen(name='vds'))
sm.add_widget(PctrsScreen(name='pctrs'))


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

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

,但是当我运行并按“文档按钮”时,出现此错误

 Traceback (most recent call last):
   File "main.py", line 45, in <module>
     MainApp().run()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/app.py", line 826, in run
     runTouchApp()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/core/window/window_pygame.py", line 403, in mainloop
     self._mainloop()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/core/window/window_pygame.py", line 289, in _mainloop
     EventLoop.idle()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/base.py", line 340, in idle
     self.dispatch_input()
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/base.py", line 325, in dispatch_input
     post_dispatch_input(*pop(0))
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/base.py", line 291, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/uix/behaviors/button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
   File "/home/parvektor228/TAOKF/lib/python3.6/site-packages/kivy/lang/builder.py", line 64, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "/home/parvektor228/TAOKF/KivyApp/memfier/main.kv", line 32, in <module>
     on_release: root.go_to_dcs()
   File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'ScreenFrame' object has no attribute 'go_to_dcs'

错误在哪里,或者我不能理解的地方吗?

更多细节,以便错误通知消失。 还有更多细节,以便错误通知消失。 还有更多细节,以便错误通知消失。

2 个答案:

答案 0 :(得分:1)

发生问题是因为ScreenFrameBoxLayout(根据您的kv文件),而不是Screen。因此,您调用的root(在这种情况下为ScreenFrame)没有与之关联的managermanagerScreen本身相关。

您必须引用ScreenFrame小部件的父小部件才能引用当前的Screen,并且它与manager相关联。为了清楚起见,我建议按照以下方式重组您的Python代码和kv文件:

Python代码:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.widget import Widget

Builder.load_file("testthis.kv")

class ScreenFrame(BoxLayout):

    def go_to_screen(self, val):
        self.parent.manager.current = val

class NtsScreen(Screen):
    pass

class DcsScreen(Screen):
    pass

class VdsScreen(Screen):
    pass

class PctrsScreen(Screen):
    pass

class MyScreenManager(ScreenManager):
    pass

class MainApp(App):

    def build(self):
        self.sm = MyScreenManager()
        return self.sm

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

kv文件:

<MyScreenManager>:
    NtsScreen:
        name: 'nts'
    DcsScreen:
        name: 'dcs'
    VdsScreen:
        name: 'vds'
    PctrsScreen:
        name: 'pctrs'

<NtsScreen>:
    ScreenFrame:

<DocsScreen>:
    ScreenFrame:

<VdsScreen>:
    ScreenFrame:

<PctrsScreen>:
    ScreenFrame:

<ScreenFrame>:

    orientation: 'vertical'
    rows: 3

    ActionBar:
        ActionView:
            pos_hint: {'top':1}
            use_separator: True
            ActionPrevious:
                title: "Title"
                with_previous: False
            ActionButton:
                text: "+"

    Label:
        text: "Content"

    BoxLayout:
        orientation: 'horizontal'
        cols: 4
        size_hint: 1, 0.15

        Button:
            text: "Notes"
            on_press: root.go_to_screen('nts')
        Button:
            text: "Docs"
            on_release: root.go_to_screen('dcs')
        Button:
            text: "Videos"
            on_release: root.go_to_screen('vds')
        Button:
            text: "Pictures"
            on_release: root.go_to_screen('pctrs')

答案 1 :(得分:0)

问题-AttributeErrors

有两个AttributeError,它们如下:

AttributeError:go_to_dcs()方法

     on_release: root.go_to_dcs()
   File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'ScreenFrame' object has no attribute 'go_to_dcs'

在kv文件中,定义了dynamic class<ScreenFrame@BoxLayout>:,但尚未实现go_to_dcs()方法。

AttributeError:管理器

     on_press: root.manager.current = 'nts'
   File "kivy/weakproxy.pyx", line 30, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'ScreenFrame' object has no attribute 'manager'

动态类<ScreenFrame@BoxLayout>:具有 BoxLayout 继承,但没有 Screen 继承。因此,它没有名为 manager 的属性。

解决方案

kv文件

  1. 用类规则<ScreenFrame@BoxLayout>:替换动态类<ScreenFrame>:
  2. 在课堂规则中,<ScreenFrame>:-将root.manager.current替换为app.root.current

摘要

<ScreenFrame>:

        Button:
            text: "Notes"
            on_press: app.root.current = 'nts'
        Button:
            text: "Docs"
            on_release: root.go_to_dcs()    
        Button:
            text: "Videos"
            on_press: app.root.current = 'vds'
        Button:
            text: "Pictures"
            on_press: app.root.current = 'pctrs'

Kv language » Three Keywords

  

Kv语言共有三个关键字:

     

app :始终引用您的应用程序实例。

     

root :是指当前规则中的基本小部件/模板

     

自身 :始终引用当前小部件

Python代码

  1. 添加导入语句from kivy.uix.boxlayout import BoxLayout
  2. class ScreenFrame():替换为class ScreenFrame(BoxLayout):

示例

main.py

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


Builder.load_file("main.kv")


class ScreenFrame(BoxLayout):
    def go_to_dcs(self):
        print("\nScreenFrame.go_to_dcs")
        sm.current = "dcs"


class NtsScreen(Screen):
    pass


class DcsScreen(Screen):
    def go_to_dcs(self):
        sm.current = 'dcs'


class VdsScreen(Screen):
    pass


class PctrsScreen(Screen):
    pass


# Create the screen manager
sm = ScreenManager()
sm.add_widget(NtsScreen(name='nts'))
sm.add_widget(DcsScreen(name='dcs'))
sm.add_widget(VdsScreen(name='vds'))
sm.add_widget(PctrsScreen(name='pctrs'))


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


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

main.kv

#:kivy 1.11.0

<ScreenFrame>:
    orientation: 'vertical'
    cols: 3

    ActionBar:
        ActionView:
            pos_hint: {'top':1}
            use_separator: True
            ActionPrevious:
                title: "Title"
                with_previous: False
            ActionButton:
                text: "+"


    Label:
        text: "Content"


    BoxLayout:
        orientation: 'horizontal'
        cols: 4
        size_hint: 1, 0.15

        Button:
            text: "Notes"
            on_press: app.root.current = 'nts'

        Button:
            text: "Docs"
            on_release: root.go_to_dcs()

        Button:
            text: "Videos"
            on_press: app.root.current = 'vds'

        Button:
            text: "Pictures"
            on_press: app.root.current = 'pctrs'

<NtsScreen>:
    BoxLayout:
        orientation: "vertical"
        cols: 2

        ScreenFrame:
        Button:
            text: "f"
            #work, but me need implementaion through function
            on_press: root.manager.current = "vds"

<DcsScreen>:
    ScreenFrame:

<VdsScreen>:
    ScreenFrame:

<PctrsScreen>:
    ScreenFrame:

输出

Img01 - App Startup Img02 - Videos Screen Img03 - Dcs Screen