Kivy:布局大小不会在应用启动时更新

时间:2020-08-28 19:33:48

标签: python checkbox kivy toggle kivy-language

我对kivy和python还是很陌生,这里的第一个问题...因此,如果复选框为空,则我想隐藏布局,以操纵大小和不透明度属性。如果您使用复选框,它会按预期工作,但是在应用运行时,将有空白空间。我试图使用构造函数和schedule_once函数将大小更改为[0,0],并且看起来像size属性发生了变化,但是仍然可以在屏幕截图中看到一个空白空间。

P.S。 我有一个假设,即与kv文件相关的问题包括在内,因为我试图为此问题创建一个简约的示例,并且...仅使用main.kv和main.py即可正常工作。

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager

kivy.require('1.11.0')

kv = """
#:import utils kivy.utils

<ValuesGridLayout@GridLayout>:
    cols: 1
    row_default_height: 30
    size_hint_y: None
    height: self.minimum_height
    spacing: 3

<MainPanelLabel@Label>:
    text_size: self.size
    valign: "middle"
    padding_x: 5
    text: "Some content"

<MainPanel>:
    kinetic_container: kinetic_container
    thread_container: thread_container
    padding: 20, 20, 20, 0
    BoxLayout:
        orientation: 'vertical'
        BoxLayout:
            ScrollView:
                GridLayout:
                    padding: [0, 10]
                    cols: 1
                    spacing: 30
                    size_hint_y: None
                    height: self.minimum_height

                    BoxLayout:
                        CheckBox:
                            size_hint: (None, None)
                            size: [20,20]
                            on_active:
                                root.toggleParameters(self.active, root.kinetic_container)

                        MainPanelLabel:
                            text: "Kinetic values:"
                            color: utils.get_color_from_hex('#f6711b')
                            font_size: '20sp'

                    ValuesGridLayout:
                        id: kinetic_container
                        visible: False
                        size: [500, 200] if self.visible else [0, 0]
                        opacity: 1 if self.visible else 0
                        disabled: not self.visible

                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel

                    BoxLayout:
                        CheckBox:
                            padding: 20
                            size_hint: (None, None)
                            size: [20,20]
                            on_active:
                                root.toggleParameters(self.active, root.thread_container)

                        MainPanelLabel:
                            text: "Thread values:"
                            color: utils.get_color_from_hex('#f6711b')
                            font_size: '20sp'

                    ValuesGridLayout:
                        id: thread_container
                        visible: False
                        size: [500, 200] if self.visible else [0, 0]
                        opacity: 1 if self.visible else 0
                        disabled: not self.visible

                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel
                        MainPanelLabel

<MainFrame>:
    id: screen_manager
    Screen:
        name: "Initial"
        MainPanel

"""


class MainPanel(BoxLayout):
    def __init__(self, **kwargs):
        super(MainPanel, self).__init__(**kwargs)
        Clock.schedule_once(lambda dt: self.initializeSize(), 0)

    def toggleParameters(self, instance, object):
        if instance:
            object.visible = True
        else:
            object.visible = False

    def initializeSize(self):
        self.kinetic_container.size = [0, 0]
        self.thread_container.size = [0, 0]


class MainFrame(ScreenManager):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class SomeApp(App):
    def build(self):
        return MainFrame()


if __name__ == "__main__":
    Builder.load_string(kv)
    SomeApp().run()

Screenshot

预先感谢!

1 个答案:

答案 0 :(得分:0)

我不确定什么会导致越野车行为,但这是罪魁祸首。

<ValuesGridLayout@GridLayout>:
    size_hint_y: None
    height: self.minimum_height
    ...

在这里,您将高度设置为self.minimum_height。但是,当您使用小部件时,您将覆盖它:

ValuesGridLayout:
    id: kinetic_container
    size: [500, 200] if self.visible else [0, 0]
    ...

(注意:设置宽度实际上没有任何作用,因为size_hint_x仍为1。)

推测:如果值不同,则属性仅调度事件。当我尝试调试它时,在应用程序启动时,首先调用height的类定义,然后调用实例定义,然后再次调用类定义。如果您使用的是self.minimum_height而不是200,那么它会起作用,因此,看起来像是由更改调度的事件在初始窗口小部件设置期间触发了某些事件。

解决方案

您可以将所有属性移到类规则中:

<ValuesGridLayout@GridLayout>:
    visible: False
    size_hint_y: None
    height: self.minimum_height if self.visible else 0
    opacity: 1 if self.visible else 0
    disabled: not self.visible
    cols: 1
    row_default_height: 30
    spacing: 3

现在您只需要

ValuesGridLayout:
    id: kinetic_container
    MainPanelLabel
    ...

ValuesGridLayout:
    id: thread_container
    MainPanelLabel
    ...

仅此而已。

奖金提示:

  • sizepaddingReferenceListProperty)与元组一起工作,因此您只需执行size: 200, 500
  • 您无需执行root.kinetic_container,只需执行kinetic_container,有关ID的范围,请参见docs
  • toggleParameters()是不必要的,您只需执行on_active: kinetic_container.visible = self.active
  • 执行以下操作,而不是定义一个空的__init__()
    class MainFrame(ScreenManager):
        pass
    

黑客很开心!

相关问题