Kivy Accordion: недостаточно места для предупреждения - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь создать меню на основе аккордеона, используя Kivy и Python 3.7 на дисплее 1366x768 (на случай, если это что-то изменит). Код, кажется, работает просто отлично, так как я получаю желаемый результат. Тем не менее, я получаю предупреждение о том, что в аккордеоне недостаточно места для всех детей (я полагаю), и раскладка будет прервана, но это не так: все нарисовано с большим количеством места. Хотя это и не является критической проблемой, поскольку все выглядит так, как ожидалось, я либо упускаю что-то очевидное, либо неправильно представляю, как 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.

1 Ответ

0 голосов
/ 07 апреля 2019

Причина, по которой вы получаете это предупреждение, заключается в том, что виджет Accordion выполняет свой код макета до того, как будет установлен его фактический размер (обычно для Accordion).Обратите внимание, что в сообщении написано need 132px.Это связано с тем, что минимальный размер по умолчанию для каждого элемента равен 44, а у вашего accord3 3 детей (3 раза 44 означает 132).Там также написано got 91px.Это потому, что начальный размер родительского GridLayout равен 100 на 100 (как и для всех виджетов), и 0,09 этого (или 9px) берется Section 3 Label, оставляя 91px для Accordion.Поскольку 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)
...