【问题标题】:Failing to get ids from kivy object无法从 kivy 对象获取 id
【发布时间】:2019-11-27 05:50:53
【问题描述】:

我正在尝试将 ID 与 ObjectProperty() 一起使用,但不像想象的那样工作。我理解 ObjectProperty 的方式是 variablename = ObjectProperty() 作为对 .kv 文件中名为 variablename 的类的引用,但我误解了一些东西,因为我收到以下错误:swiper_manager = MySwiperManager.ids.swiper_manager AttributeError: 'kivy.properties.ObjectProperty' object has no attribute 'ids'

.py 文件

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty
from kivy.lang import Builder

from kivymd.uix.managerswiper import MDSwiperPagination
from kivymd.theming import ThemeManager

Builder.load_file("Prelogin/prescreenmanger.kv")

class MySwiperManager(BoxLayout):
    pass

class PreScreenManager(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Indigo'
    MySwiperManager = ObjectProperty()
    swiper_manager = MySwiperManager.ids.swiper_manager
    paginator = MDSwiperPagination()
    paginator.screens = swiper_manager.screen_names
    paginator.manager = swiper_manager
    swiper_manager.paginator = paginator
    MySwiperManager.add_widget(paginator)

.kv 文件

<ScreenOne@Screen>:
    name: 'screen one'
    Label: 
        text: 'Hello World'

<ScreenTwo@Screen>:
    name: 'screen two'


<ScreenThree@Screen>:
    name: 'screen three'


<ScreenFour@Screen>:
    name: 'screen four'



<ScreenFive@Screen>:
    name: 'screen five'


<PreScreenManager>:
    MySwiperManager:
        orientation: 'vertical'
        id: MySwiperManager

        MDSwiperManager:
            id: swiper_manager

            ScreenOne: 

            ScreenTwo:

            ScreenThree:

            ScreenFour:

            ScreenFive:

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.factory import Factory
from kivymd.theming import ThemeManager

from Prelogin.prescreenmanger import PreScreenManager

class MainApp(App):
    pass

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

main.kv

AnchorLayout:
    canvas.before:
        Rectangle:
            size: self.size
            pos: self.pos
            source: "Start/Background.png"   
    anchor_x: 'center'
    anchor_y: 'top'
    Image:
        source: 'Start/Loginlogo.png'
        keep_ratio: False
        allow_stretch: True
        opacity: 1
        size_hint: 1, 0.25
        pos_hint: (0,0)  
    ScreenManager:
        id: screen_manager
        PreScreenManager:
            id: PreScreenManager

这是我拥有的代码的更新版本。 .py 文件

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

from kivymd.uix.managerswiper import MDSwiperPagination
from kivymd.theming import ThemeManager

Builder.load_file("Prelogin/prescreenmanger.kv")

class MySwiperManager(BoxLayout):
    pass

class PreScreenManager(Screen):
    swiper_manager = ObjectProperty()  # reference to MySwiperManager from kv file

    def do_setup(self, dt):
        # code to do the setup (called after App is instantiated)
        paginator = MDSwiperPagination()
        paginator.screens = self.swiper_manager.screen_names
        paginator.manager = self.swiper_manager
        self.swiper_manager.paginator = paginator
        self.swiper_manager.add_widget(paginator)

.kv 文件

<ScreenOne@Screen>:
    name: 'screen one'
    Label: 
        text: 'Hello World'
        color: 1,1,1

<ScreenTwo@Screen>:
    name: 'screen two'


<ScreenThree@Screen>:
    name: 'screen three'


<ScreenFour@Screen>:
    name: 'screen four'


<ScreenFive@Screen>:
    name: 'screen five'


<PreScreenManager>:
    swiper_manager: swiper_manager  # uses the id from below

    MySwiperManager:
        orientation: 'vertical'

        MDSwiperManager:
            id: swiper_manager

            ScreenOne:

            ScreenTwo:

            ScreenThree:

            ScreenFour:

            ScreenFive:

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.factory import Factory
from kivy.clock import Clock
from kivymd.theming import ThemeManager

from Prelogin.prescreenmanger import PreScreenManager

class MainApp(App):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Indigo'
    def build(self):
        # create an instance of PreScreenManager
        psm = PreScreenManager()

        # schedule the execution of the do_setup() method
        Clock.schedule_once(psm.do_setup)

        # return the PreScreenManager instance as the root of the App display
        return psm

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

main.kv

AnchorLayout:
    canvas.before:
        Rectangle:
            size: self.size
            pos: self.pos
            source: "Start/Background.png"   
    anchor_x: 'center'
    anchor_y: 'top'
    Image:
        source: 'Start/Loginlogo.png'
        keep_ratio: False
        allow_stretch: True
        opacity: 1
        size_hint: 1, 0.25
        pos_hint: (0,0)  
    ScreenManager:
        id: screen_manager
        PreScreenManager:
            id: PreScreenManager

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    我想我几乎理解你想要做什么了。要在您的PreScreenManager 中自动设置swiper_manager,请先将该属性添加到您的prescreenmanger.kv 文件中:

    <PreScreenManager>:
        swiper_manager: swiper_manager  # uses the id from below
        my_sm: msm  # uses the id from below
    
        MySwiperManager:
            orientation: 'vertical'
            id: msm
    
            MDSwiperManager:
                id: swiper_manager
    
                ScreenOne:
    
                ScreenTwo:
    
                ScreenThree:
    
                ScreenFour:
    
                ScreenFive:
    

    我冒昧地将id 更改为msm,因为使用类名只会导致混淆。然后,修改你的 PreScreenManager 类:

    class PreScreenManager(Screen):
        swiper_manager = ObjectProperty()  # reference to MDSwiperManager from kv file
        my_sm: ObjectProperty()  # reference to MySwiperManager from kv file
    
        def do_setup(self, dt):
            # code to do the setup (called after App is instantiated)
            theme_cls = ThemeManager()
            theme_cls.primary_palette = 'Indigo'
            paginator = MDSwiperPagination()
            paginator.screens = self.swiper_manager.screen_names
            paginator.manager = self.swiper_manager
            self.swiper_manager.paginator = paginator
            self.my_sm.add_widget(paginator)
    

    我从未使用过kivyMD,因此我无法保证do_setup() 方法中代码的正确性。最后,通过修改MainApp 类来安排do_setup() 方法的执行:

    class MainApp(App):
        def build(self):
            # create an instance of PreScreenManager
            psm = PreScreenManager()
    
            # schedule the execution of the do_setup() method
            Clock.schedule_once(psm.do_setup)
    
            # return the PreScreenManager instance as the root of the App display
            return psm
    

    【讨论】:

    • 是的,这就是我想要做的,谢谢。当我运行您编写的代码时,我得到AttributeError: 'MainApp' object has no attribute 'theme_cls',所以我将theme_cls = ThemeManager() theme_cls.primary_palette = 'Indigo' 添加到MainApp,但现在我得到paginator.screens = self.swiper_manager.screen_names AttributeError: 'NoneType' object has no attribute 'screen_names'
    • 该错误表明swiper_manager 未设置。仔细查看我的答案,并确保您已正确实施我的建议。而且,是的,将theme_cls 的东西移到MainApp
    • 是的,我错过了对 .kv 文件的导入(我已经修改该文件以测试是否可以使其工作)但知道错误消息是 ``AttributeError: 'MySwiperManager' object没有属性'screen_names'````。
    • 我想我现在可能已经解决了。等我知道了会回信的。
    • 我明白了。也许swiper_manager: msm # uses the id from below 应该是swiper_manager: swiper_manager # uses the id from below
    【解决方案2】:
    swiper_manager = MySwiperManager.ids.swiper_manager
    

    您将类定义(MySwiperManager)与类的实例(例如MySwiperManager())混淆了。通常你所有的代码都应该在实例级别,把东西放在类级别通常是错误的,但这是一个常见的错误。

    不可能给出具体的解决方案,因为您的示例不完整(实际上它还有其他几个问题,总是提供一个最小的 runnable 示例以使事情变得更容易),但一般答案是您想访问MySwiperManager 类实例的ids 属性。

    【讨论】:

    • 感谢您的评论。我只是添加了缺少的 .py 和 .kv 文件,使其成为可运行的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多