【问题标题】:How in Kivy to implement the transition to a new Screen through the function?在Kivy中如何通过该功能实现到新Screen的过渡?
【发布时间】:2018-07-31 19:12:49
【问题描述】:

我想在单击按钮后实现到新屏幕的转换,我想通过函数来​​实现。 我有这个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'

错误在哪里,或者我有什么不明白的地方吗?

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

【问题讨论】:

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


    【解决方案1】:

    问题 - AttributeErrors

    有两个AttributeErrors,它们如下:

    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&lt;ScreenFrame@BoxLayout&gt;:,但没有实现 go_to_dcs() 方法。

    属性错误:管理器

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

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

    解决方案

    kv 文件

    1. 用类规则&lt;ScreenFrame&gt;:替换动态类&lt;ScreenFrame@BoxLayout&gt;:
    2. 在类规则中,&lt;ScreenFrame&gt;: - 将 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:指当前规则中的基础小部件/模板

    self:始终引用当前小部件

    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:
    

    输出

    【讨论】:

    • 嗨,你知道为什么按下文档按钮时会出现黑窗吗?
    • screen name="dcs" 的黑屏是由于类名不匹配。在 Python 代码中,它是 class DcsScreen(Screen),但在 kv 文件中,它是 &lt;DocsScreen&gt;:。通过在 kv 文件中将课程规则 &lt;DocsScreen&gt;: 替换为 &lt;DcsScreen&gt;: 来更新帖子。
    【解决方案2】:

    出现您的问题是因为 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')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      相关资源
      最近更新 更多