Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KivyMD crashes if anchor is set to top when MDNavagationRail has neither MenuButton nor FabButton. #1743

Open
mnishig opened this issue Sep 30, 2024 · 0 comments

Comments

@mnishig
Copy link

mnishig commented Sep 30, 2024

Description of the Bug

My app has some MDNavigationRailItem only and set anchor is top, KivyMD is crashed with message “attributeError: ‘NoneType’ object has no attribute 'y'”.

Reproduce Code

These are almost same of document's example expect add "anchor: 'top"

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty

from kivymd.app import MDApp
from kivymd.uix.navigationrail import MDNavigationRailItem

KV = '''
<CommonNavigationRailItem>
    MDNavigationRailItemIcon:
        icon: root.icon

    MDNavigationRailItemLabel:
        text: root.text

MDBoxLayout:
    MDNavigationRail:
        type: "selected"
        anchor: 'top'

        # MDNavigationRailMenuButton:
        #     icon: "menu"

        # MDNavigationRailFabButton:
        #     icon: "home"

        CommonNavigationRailItem:
            icon: "format-list-bulleted"
            text: "file list"

        CommonNavigationRailItem:
            icon: 'eraser'
            text: 'eraser'

    MDScreen:
        md_bg_color: self.theme_cls.secondaryContainerColor
'''

class CommonNavigationRailItem(MDNavigationRailItem):
    text = StringProperty()
    icon = StringProperty()

class MDRailApp(MDApp):
    def build(self):
        return Builder.load_string(KV)

MDRailApp().run()

log

[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "/media/mnishi/opt/ws-sf/ui/md-nrail.py", line 51, in <module>
     MDRailApp().run()
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/app.py", line 956, in run
     runTouchApp()
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/base.py", line 339, in mainloop
     self.idle()
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/base.py", line 379, in idle
     Clock.tick()
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/clock.py", line 733, in tick
     self.post_idle(ts, self.idle())
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivy/clock.py", line 776, in post_idle
     self._process_events()
   File "kivy/_clock.pyx", line 620, in kivy._clock.CyClockBase._process_events
   File "kivy/_clock.pyx", line 653, in kivy._clock.CyClockBase._process_events
   File "kivy/_clock.pyx", line 649, in kivy._clock.CyClockBase._process_events
   File "kivy/_clock.pyx", line 218, in kivy._clock.ClockEvent.tick
   File "/media/mnishi/opt/ws-sf/ui/.venv/lib/python3.12/site-packages/kivymd/uix/navigationrail/navigationrail.py", line 770, in set_top_pos
     anchor_button.y
 AttributeError: 'NoneType' object has no attribute 'y'

cause

MDNavigationRail.py decide anchor y value by _check_anchor() method.
if both MenuButton and FacButton are nothing, anchor_button set None in _check_anchor().

work around

I’m not sure the correct anchor y criteria, so I patch based on height of MDNavigationRail.

    def _check_anchor(self, *args):
        def set_top_pos(*args):
            anchor_y = 0
            if (
                self.fab_button
                and not self.menu_button
                or self.fab_button
                and self.menu_button
            ):
                anchor_button = self.fab_button
                anchor_y = self.fab_button.y
            elif self.menu_button and not self.fab_button:
                anchor_y = self.menu_button.y

            # both MenuButton and FabButton dose not exist  CASE
            else:
                anchor_y = self.height

            self.ids.box_items.y = (
                anchor_y
                - (len(self.ids.box_items.children) * dp(56))
                - dp(56)
            )

        if self.anchor == "center":
            self.ids.box_items.pos_hint = {"center_y": 0.5}
        elif self.anchor == "top":
            Clock.schedule_once(set_top_pos)
        elif self.anchor == "bottom":
            self.ids.box_items.y = dp(56)

        if self.anchor == "center":
            self.ids.box_items.pos_hint = {"center_y": 0.5}
        elif self.anchor == "top":
            Clock.schedule_once(set_top_pos)
        elif self.anchor == "bottom":
            self.ids.box_items.y = dp(56)

$ diff kivymd/kivymd/uix/navigationrail/navigationrail.py ./navigationrail.py

747c747
<             anchor_button = None
---
>             anchor_y = 0
754a755
>                 anchor_y = self.fab_button.y
756c757,759
<                 anchor_button = self.menu_button
---
>                 anchor_y = self.menu_button.y
>             else:
>                 anchor_y = self.height
759c762
<                 anchor_button.y
---

MDNavigarionrail-0930

Versions

  • OS: Linux Mint 22 (wilma) , cat /etc/upstream-release/lsb-release >> Ubuntu 24.04
  • Python: 3.12.3
  • Kivy: v2.3.0
  • KivyMD: 2.0.1.dev0, git-5ff9d0d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant