Kivy:版面大小不会在应用程序启动时更新

2024-09-27 19:22:38 发布

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

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

附言。 我有一个假设,与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

非常感谢


Tags: fromimportselfnonesizeifcontainerthread
1条回答
网友
1楼 · 发布于 2024-09-27 19:22:38

我不确定到底是什么导致了童车行为,但罪魁祸首在这里

<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。)

Speculation: Properties only dispatch events if the value is different. When I tried debugging it, on the launch of the app the class definition of height was called first, then the instance definition, then the class definition again. If you’d have used self.minimum_height instead of 200, it would have worked, so it looks like the event dispatched by the change triggers something during the initial widget setup.

溶液

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

<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
    ...

就这些

奖励提示:

  • sizepadding^{})使用元组,所以您可以只做size: 200, 500
  • 您不需要执行root.kinetic_container,只需执行kinetic_container即可,请参阅docs了解id的作用域
  • toggleParameters()是不必要的,您只需执行on_active: kinetic_container.visible = self.active
  • 不要定义一个空的__init__(),只需
    class MainFrame(ScreenManager):
        pass
    

快乐的黑客

相关问题 更多 >

    热门问题