如何在 Kivy 中设置小部件/布局的最小允许宽度/高度? [英] How do I set minimum allowable width/height for widget/layout in Kivy?
问题描述
我有带有 3 个元素的 BoxLayout,我需要第一个和最后一个元素占用最小的可用空间.中间元素的比例是固定的(1:1),所以当我调整窗口大小时,侧面元素变得太小,内容就会消失.我需要例如标签(或按钮,甚至不同元素的集合)文本始终位于标签内部.这个大小不应该更大,所以我可以说它应该是固定大小,取决于它的内容.
I have BoxLayout with 3 elements, I need that first and last elements to occupy minimum available space. Middle element has fixed proportion (1:1), so when I resize the window, side elements become too small and content go out of it. I need e.g. label's (or button's, or even set's of different elements) text to be always inside the label. This size shouldn't be more, so I can say it should be fixed size depending on its content.
更新:我犯了一个错误,大小可以更多,但不能更小.那应该怎么做呢?
UPDATE: I've made a mistake, size can be more, but not less. How it should be then?
更新:所以这是我的 BoxLayout:当我展开窗口时,只有侧面部分应该展开:当我收缩窗口时,侧面部分应该有一些最小尺寸:所以我认为这是一个固定的最小值.
UPDATE: So it's my BoxLayout: When I expand the window, only side parts should expand: And when I constrict the window, side parts should have some minimum size: So it's kind of fixed minimum I think.
推荐答案
Label
的内容大小可以通过texture_size
属性获得,所以你可以设置size_hint
为 None 并将大小绑定到内容大小:
Content size of Label
is avaiable through texture_size
property, so you can set size_hint
to None and bind size to content size:
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
属性.来自 文档:通过默认情况下,标签不受任何边界框的约束.您可以使用此属性设置标签的大小约束.文本将自动流入约束.因此虽然字体大小不会减小,但文本会被排列以适应尽可能最好地放入框内,任何仍在框外的文本都被剪掉".例如:
You should also check text_size
property. From documentation: "By default, the label is not constrained to any bounding box. You can set the size constraint of the label with this property. The text will autoflow into the constrains. So although the font size will not be reduced, the text will be arranged to fit into the box as best as possible, with any text still outside the box clipped". For example:
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()
).例如:
UPDATE
If you want even more control about the way widgets scale, you can create method which calculate values for widgets and have it binded to changing size property (either bind
or implementing on_size()
). For example:
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()
这篇关于如何在 Kivy 中设置小部件/布局的最小允许宽度/高度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!