首页 > 解决方案 > Kivy Accordion:空间不足警告

问题描述

我正在尝试在 1366x768 显示器中使用 Kivy 和 Python 3.7 制作基于手风琴的菜单(以防它有所作为)。当我得到所需的输出时,代码似乎工作得很好。但是,我收到警告说手风琴中没有足够的空间供所有孩子使用(我想)并且布局将被中止,但事实并非如此:所有内容都以足够的空间绘制。虽然这不是一个关键问题,但正如预期的那样,我要么遗漏了一些明显的东西,要么对 kivy 如何生成屏幕元素有误解。因此,如果您能澄清这一点(并希望摆脱丑陋的警告),我将不胜感激!

下面是代码的简化版本,全部使用纯 python(我想保持这种方式,它不是一个复杂的程序)。我只是制作了一个外部 BoxLayout,并在里面放置了一个带有手风琴的内部 GridLayout,下方有一个按钮。请注意,我已将 kivy 设置为作为最大化窗口运行,对此的设置包含在代码中。

起初我认为它可能与 kivy 处理项目或其他东西的顺序有关:它可能首先检查标签和按钮,假设默认 size_hint=(1, 1) 并认为它没有空间,但随后能够绘制它们感谢自定义 size_hint。但是,当将其更改为 (1, 1) 时,我收到了相同的警告,同时仍然将所有内容都绘制有空间(尽管不是很多)。不过,它确实略微改变了警告,因为它显示了更多警告和更严格的限制。

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.accordion import Accordion, AccordionItem
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.app import App

from kivy.config import Config


class TestApp(App):
    def build(self):
        layout = BoxLayout(orientation="vertical")

        inner_layout = GridLayout(cols=3)
        inner_layout.add_widget(Label(text="Section 1", size_hint=(1, 0.09), font_size='20dp'))
        inner_layout.add_widget(Label(text="Section 2", size_hint=(1, 0.09), font_size='20dp'))
        inner_layout.add_widget(Label(text="Section 3", size_hint=(1, 0.09), font_size='20dp'))

        accord1 = Accordion(orientation="vertical")
        accord1.add_widget(AccordionItem(title="Item 1"))
        accord1.add_widget(AccordionItem(title="Item 2"))

        accord2 = Accordion(orientation="vertical")
        accord2.add_widget(AccordionItem(title="Item 1"))

        accord3 = Accordion(orientation="vertical")
        accord3.add_widget(AccordionItem(title="Item 1"))
        accord3.add_widget(AccordionItem(title="Item 2"))
        accord3.add_widget(AccordionItem(title="Item 3"))

        inner_layout.add_widget(accord1)
        inner_layout.add_widget(accord2)
        inner_layout.add_widget(accord3)

        layout.add_widget(inner_layout)

        continue_btn = Button(text="START", size_hint=(1, 0.07))
        layout.add_widget(continue_btn)

        return layout


if __name__ == "__main__":
    # Three lines to ensure non-fullscreen, maximized window on launch
    Config.set('graphics', 'fullscreen', 0)
    Config.set('graphics', 'borderless', 0)
    Config.set('graphics', 'window_state', 'maximized')

    Config.write()

    TestApp().run()

这是我使用显示的代码得到的警告:

[WARNING] [Accordion   ] not enough space for displaying all children
[WARNING] [Accordion   ] need 132px, got 91px
[WARNING] [Accordion   ] layout aborted.

虽然这些是将所有 size_hint 值更改为默认值 (1, 1) 的结果:

[WARNING] [Accordion   ] not enough space for displaying all children
[WARNING] [Accordion   ] need 88px, got 50px
[WARNING] [Accordion   ] layout aborted.
[WARNING] [Accordion   ] not enough space for displaying all children
[WARNING] [Accordion   ] need 132px, got 50px
[WARNING] [Accordion   ] layout aborted.

标签: pythonpython-3.xlayoutkivyaccordion

解决方案


您收到该警告的原因是该Accordion小部件在设置其实际大小之前正在运行其布局代码(对于 来说是正常的Accordion)。请注意,消息说need 132px。这是因为每个项目的默认最小尺寸是 44,并且您accord3有 3 个孩子(3 乘以 44 是 132)。它还说got 91px。这是因为父级的初始大小GridLayout是 100 x 100(对于所有小部件都是如此),其中 0.09(或 9px)Section 3 LabelAccordion. 由于 91 小于 132,所以判断空间不足。正确,但不久之后,再次使用正确的值调用布局代码,一切都很好。如果该代码的作者能够消除那些无意义的警告,那就太好了。

因此,您可以通过在确定其实际大小之前不将Accordion小部件添加到布局中来避免这些警告。GridLayout为此,您可以使用Clock.schedule_once(). 这是您TestApp使用该方法的修改:

class TestApp(App):
    def build(self):
        layout = BoxLayout(orientation="vertical")

        self.inner_layout = GridLayout(cols=3)
        self.inner_layout.add_widget(Label(text="Section 1", size_hint=(1, 0.09), font_size='20dp'))
        self.inner_layout.add_widget(Label(text="Section 2", size_hint=(1, 0.09), font_size='20dp'))
        self.inner_layout.add_widget(Label(text="Section 3", size_hint=(1, 0.09), font_size='20dp'))

        layout.add_widget(self.inner_layout)

        continue_btn = Button(text="START", size_hint=(1, 0.07))
        layout.add_widget(continue_btn)

        Clock.schedule_once(self.add_accordions)

        return layout

    def add_accordions(self, dt):

        accord1 = Accordion(orientation="vertical")
        accord1.add_widget(AccordionItem(title="Item 1"))
        accord1.add_widget(AccordionItem(title="Item 2"))

        accord2 = Accordion(orientation="vertical")
        accord2.add_widget(AccordionItem(title="Item 1"))

        accord3 = Accordion(orientation="vertical")
        accord3.add_widget(AccordionItem(title="Item 1"))
        accord3.add_widget(AccordionItem(title="Item 2"))
        accord3.add_widget(AccordionItem(title="Item 3"))

        self.inner_layout.add_widget(accord1)
        self.inner_layout.add_widget(accord2)
        self.inner_layout.add_widget(accord3)

推荐阅读