【问题标题】:How do I set minimum allowable width/height for widget/layout in Kivy?如何在 Kivy 中设置小部件/布局的最小允许宽度/高度?
【发布时间】:2014-09-08 08:07:30
【问题描述】:

我有带有 3 个元素的 BoxLayout,我需要第一个和最后一个元素占用最小的可用空间。中间元素的比例是固定的(1:1),所以当我调整窗口大小时,侧面元素变得太小,内容超出了它。我需要例如标签(或按钮,甚至不同元素的集合)文本始终位于标签内部。这个大小不应该更大,所以我可以说它应该是固定大小,具体取决于它的内容。

更新: 我犯了一个错误,大小可以更多,但不能更小。那应该怎么做呢?

更新: 所以这是我的 BoxLayout: 当我展开窗口时,只有侧面部分应该展开: 当我收缩窗口时,侧面部分应该有一些最小尺寸: 所以我认为这是一个固定的最小值。

【问题讨论】:

    标签: python-3.x size kivy python-3.4


    【解决方案1】:

    Label 的内容大小可通过 texture_size 属性获得,因此您可以将 size_hint 设置为 None 并将大小绑定到内容大小:

    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button 
    
    from kivy.lang import Builder
    
    kv = '''
    <MyButton>:
        size_hint: None, 1
        size: self.texture_size
    '''
    Builder.load_string(kv)
    
    class MyButton(Button):
        pass
    
    class MyWidget(BoxLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.add_widget(MyButton(text="Fixed size button"))
            self.add_widget(Button(text="Normal button"))
            self.add_widget(MyButton(text="Fixed size button"))         
    
    class MyApp(App):
        def build(self):
            return MyWidget()
    
    if __name__ == '__main__':
        MyApp().run()
    

    您还应该检查text_size 属性。来自documentation:“默认情况下,标签不受任何边界框的约束。您可以使用此属性设置标签的大小约束。文本将自动流入约束。因此虽然字体大小不会减小,文本将被安排到尽可能适合框的位置,而框外的任何文本都将被剪掉”。例如:

    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button 
    
    from kivy.lang import Builder
    
    kv = '''
    <MyButton>:
        text_size: self.size
        valign: "middle"
        halign: "center"
    '''
    Builder.load_string(kv)
    
    class MyButton(Button):
        pass
    
    class MyWidget(BoxLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.add_widget(MyButton(text="Example text which is too long to fit in one line"))
            self.add_widget(Button(text="Normal button"))
            self.add_widget(MyButton(text="Example text which is too long to fit in one line"))
    
    class MyApp(App):
        def build(self):
            return MyWidget()
    
    if __name__ == '__main__':
        MyApp().run()
    

    更新 如果您想要更多地控制小部件的缩放方式,您可以创建计算小部件值并将其绑定到更改大小属性的方法(bind 或实现on_size())。例如:

    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.widget import Widget
    from kivy.uix.label import Label
    
    from kivy.lang import Builder
    
    from functools import partial
    
    kv = '''
    <CentralWidget>:
        pos_hint: {'center_y': .5} 
        size_hint: None, None
        canvas:
            Color:
                rgb: 1, 0, 1
            Rectangle:
                pos: self.pos
                size: self.size
    
    <SideWidget>:
        pos_hint: {'center_y': .5} 
        size_hint: None, 1
        canvas.before:
            Color:
                rgb: 0, 0, 1
            Rectangle:
                pos: self.pos
                size: self.size
    '''
    
    Builder.load_string(kv)
    
    class CentralWidget(Widget):
        pass
    
    class SideWidget(Label):
        pass
    
    class MyWidget(BoxLayout):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
    
            w1 = SideWidget(text="............................")
            w2 = CentralWidget()
            w3 = SideWidget(text="............................")
    
            self.add_widget(w1)
            self.add_widget(w2)
            self.add_widget(w3)
    
        def on_size(self, *args):
            # self.size - size of parent widget
            # self.children - children of widget
            # self.children[0].texture_size - sife of content of selectend children widget
            # self.children[0].size - size of selected children widget to set
            if((self.size[0]-500)/2 > self.children[0].texture_size[0]):
                self.children[0].size = ((self.size[0]-500)/2, 0)     
                self.children[1].size = (500, 500)   
                self.children[2].size = ((self.size[0]-500)/2, 0)   
            else:
                self.children[1].size = (self.size[0]-2*self.children[0].texture_size[0], self.size[0]-2*self.children[0].texture_size[0])  
    
    class MyApp(App):
        def build(self):
            return MyWidget()
    
    if __name__ == '__main__':
        MyApp().run()
    

    【讨论】:

    • 我已经编辑了我的问题,你能扩展你的答案吗?
    • 好的,我已经添加了图片和描述。
    • 不知为何on_size() 不会在每次启动时触发,它是随机发生的。在窗口调整大小时,它每次都会触发。
    • @Necronomicron,如果你在__init__() 中添加self.size = (0, 0) 会怎样?
    • Clock.schedule_once(self.on_size, 0)(或将 0.1 作为第二个参数)怎么样?
    猜你喜欢
    • 2015-12-07
    • 1970-01-01
    • 2012-05-27
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多