Kivy手风琴:没有足够的空间警告

时间:2019-04-04 17:26:58

标签: python python-3.x layout kivy accordion

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

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

起初,我认为这可能与订单处理流程或某些事项有关:它可能首先检查标签和按钮,并假设其默认大小为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.

1 个答案:

答案 0 :(得分:0)

收到该警告的原因是Accordion小部件在设置其实际大小之前运行其布局代码(Accordion的正常大小)。请注意,该消息显示为need 132px。这是因为每个项目的默认最小大小为44,并且您的accord3有3个子项(44的132是3)。它还说got 91px。这是因为父级GridLayout的初始大小是100 x 100(所有小部件都一样),而其中的0.09(或9px)由Section 3 Label占用,为Accordion保留91px。由于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)