在Kivy(Python)中部分可见的下拉列表

2024-04-25 09:28:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用Kivy(Python的GUI)创建一个通用的菜单栏,但是我在下拉菜单方面遇到了麻烦。它们只是部分出现,我不知道为什么(参见子菜单1):

enter image description here

下面是我的代码,如果你想检查它:

#!/usr/bin/env python3

from kivy.app import App
#from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.dropdown import DropDown
from kivy.properties import ListProperty, ObjectProperty
#from kivy.uix.actionbar import ActionBar, ActionView, ActionGroup, ActionButton

class MenuItem(ButtonBehavior, Label):
    '''Background color, in the format (r, g, b, a).'''
    background_color_normal = ListProperty([0.2, 0.2, 0.2, 1])
    background_color_down = ListProperty([0.3, 0.3, 0.3, 1])
    background_color = ListProperty()
    separator_color = ListProperty([0.8, 0.8, 0.8, 1])
    pass

class MenuSubmenu(MenuItem):
    # The list of submenu items in dropdown menu
    submenu = ObjectProperty(None)

    def add_widget(self, submenu, **kwargs):
        if isinstance(submenu, MenuDropDown):
            self.submenu = submenu
        super().add_widget(submenu, **kwargs)

    def on_release(self, **kwargs):
        super().on_release(**kwargs)
        self.submenu.open(self)

class MenuDropDown(DropDown):
    pass

class MenuButton(MenuItem):
    pass

class MenuBar(BoxLayout):

    '''Background color, in the format (r, g, b, a).'''
    background_color = ListProperty([0.2, 0.2, 0.2, 1])
    separator_color = ListProperty([0.8, 0.8, 0.8, 1])

    def __init__(self, **kwargs):
        self.itemsList = []
        super().__init__(**kwargs)

    def add_widget(self, item, index=0):
        if not isinstance(item, MenuItem):
            raise TypeError("MenuBar accepts only MenuItem widgets")
        super().add_widget(item, index)
        if index == 0:
            index = len(self.itemsList)
        self.itemsList.insert(index, item)

class MenuApp(App):

    def button(self, nb):
        print("Button", nb, "triggered")

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

这里是kv文件:

^{pr2}$

如果你知道发生了什么,或者你能把我转到更合适的地方去寻找答案,那就太好了。在


Tags: fromimportselfindexdefwidgetkwargsclass
1条回答
网友
1楼 · 发布于 2024-04-25 09:28:25

正如@increment警告我没有正确使用dropdown。你不应该直接在一个kv文件中添加一个下拉窗口小部件。在

因此,我研究了kivy中的actionbar(解释here和源代码here)是如何工作的,因此我更新了我的菜单栏。在

下面是我的python代码:

#!/usr/bin/env python3

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.dropdown import DropDown
from kivy.uix.spinner import Spinner
from kivy.properties import ListProperty, ObjectProperty,\
        StringProperty, BooleanProperty, NumericProperty
#from kivy.uix.actionbar import ActionBar, ActionView, ActionGroup, ActionButton

class MenuItem(Widget):
    '''Background color, in the format (r, g, b, a).'''
    background_color_normal = ListProperty([0.2, 0.2, 0.2, 1])
    background_color_down = ListProperty([0.3, 0.3, 0.3, 1])
    background_color = ListProperty([])
    separator_color = ListProperty([0.8, 0.8, 0.8, 1])
    text_color = ListProperty([1,1,1,1])
    inside_group = BooleanProperty(False)
    pass

class MenuSubmenu(MenuItem, Spinner):
    triangle = ListProperty()

    def __init__(self, **kwargs):
        self.list_menu_item = []
        super().__init__(**kwargs)
        self.dropdown_cls = MenuDropDown

    def add_widget(self, item):
        self.list_menu_item.append(item)
        self.show_submenu()

    def show_submenu(self):
        self.clear_widgets()
        for item in self.list_menu_item:
            item.inside_group = True
            self._dropdown.add_widget(item)

    def _build_dropdown(self, *largs):
        if self._dropdown:
            self._dropdown.unbind(on_dismiss=self._toggle_dropdown)
            self._dropdown.dismiss()
            self._dropdown = None
        self._dropdown = self.dropdown_cls()
        self._dropdown.bind(on_dismiss=self._toggle_dropdown)

    def _update_dropdown(self, *largs):
        pass

    def _toggle_dropdown(self, *largs):
        self.is_open = not self.is_open
        ddn = self._dropdown
        ddn.size_hint_x = None
        if not ddn.container:
            return
        children = ddn.container.children
        if children:
            ddn.width = max(self.width, max(c.width for c in children))
        else:
            ddn.width = self.width
        for item in children:
            item.size_hint_y = None
            item.height = max([self.height, 48])

    def clear_widgets(self):
        self._dropdown.clear_widgets()

class MenuDropDown(DropDown):
        pass

class MenuButton(MenuItem,Button):
    icon = StringProperty(None, allownone=True)
    pass

class MenuEmptySpace(MenuItem):
    pass

class MenuBar(BoxLayout):

    '''Background color, in the format (r, g, b, a).'''
    background_color = ListProperty([0.2, 0.2, 0.2, 1])
    separator_color = ListProperty([0.8, 0.8, 0.8, 1])

    def __init__(self, **kwargs):
        self.itemsList = []
        super().__init__(**kwargs)

    def add_widget(self, item, index=0):
        if not isinstance(item, MenuItem):
            raise TypeError("MenuBar accepts only MenuItem widgets")
        super().add_widget(item, index)
        if index == 0:
            index = len(self.itemsList)
        self.itemsList.insert(index, item)

if __name__ == '__main__':

    class MenuApp(App):
        def button(self, nb):
            print("Button", nb, "triggered")

    MenuApp().run()

下面是相应的文件menu.kv

^{pr2}$

希望它能帮助其他想做菜单栏的人。在

相关问题 更多 >