python - Kivy(Python):如何根据其子项更改 BoxLayout 高度?
问题描述
我在 Kivy 中编写了一个新闻应用程序,该应用程序从网站的首页获取文章并使其在应用程序中可见。根据文章的长度,段落的大小和数量可能会有所不同。由于它使用 BS4 webscraper 来提取网站的内容,因此整个 gui 编程都是在 python 中进行的,而不是在 .kv 语言中。所以,我的问题是,我怎样才能停止Image
在屏幕上保留空间(我希望标签总是在它下面)以及如何根据它的孩子来改变height
aBoxLayout
的空间,以便所有人都有足够的空间,但是不要太多。
这是我的代码的简化版本,它演示了我的问题。在此示例中,a 的高度BoxLayout
设置为1000dp
适合大约 4 段,但如果有更多,它将变得混乱。有没有办法避免这个问题?任何帮助都会很有用。
from kivymd.app import MDApp
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.label import MDLabel
from kivy.uix.screenmanager import Screen
from kivy.uix.scrollview import ScrollView
from kivy.uix.image import AsyncImage
class RootWidget(Screen):
def __init__(self, **kw):
super().__init__(**kw)
self.update()
def update(self):
paragraphs_text = ["Lorem ipsum dolor sit amet,", "consectetur adipiscing elit, sed do eiusmod tempor incididunt ut"
" labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco "
"laboris nisi ut aliquip ex ea commodo consequat.", "Duis aute irure dolor in reprehenderit in"
" voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat "
"non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."]
header_text = "Lorem ipsum dolor sit amet"
header_image_src = "images/Cariboo_Peaks.jpg"
date_of_publishing_text = "03.05.2020"
scroll_widget_holder = ScrollView()
widget_holder = BoxLayout(orientation="vertical", size_hint_y=None, padding=5)
# minimum_height doesnt work in python, only in .kv language so is there a way to get the height automatically?
# 1000dp works fine for this amount of paragrpahs but i there was twice as many as there are now it would all
# become to cludderd and the image would be very small
# on the other hand, if I make this number too big the wigets are too far apart from each other
# So how can I fix this?
widget_holder.height = "1000dp"
header_image = AsyncImage(source=header_image_src, size_hint=(1, 1),
allow_stretch=False, keep_ratio=True)
header_label = MDLabel(text=header_text, size_hint_y=None, font_style="H6")
# Thats what I came up with, if there is a better way of automatically asigning the height of a widget based
# on its contents please let me know
header_label.height = str(len(header_label.text)) + "dp"
# This label is supossed to be right unter the header label(see the screens below to see my go to result created
# in photoshop)
header_date_label = MDLabel(text=date_of_publishing_text, size_hint_y=None, font_style="Caption", height="10dp")
widget_holder.add_widget(header_image)
widget_holder.add_widget(header_label)
widget_holder.add_widget(header_date_label)
for paragraph in paragraphs_text:
text_paragraph = MDLabel(text=paragraph, size_hint_y=None,
pos_hint={"center_x": .5}, halign="justify")
text_paragraph.height = str(len(text_paragraph.text)) + "dp"
widget_holder.add_widget(text_paragraph)
scroll_widget_holder.add_widget(widget_holder)
self.add_widget(scroll_widget_holder)
class TestApp(MDApp):
def build(self):
return RootWidget()
if __name__ == '__main__':
TestApp().run()
解决方案
BoxLayout
您可以通过添加所有子项(包括padding
和spacing
)的高度来计算自己的高度。如果您在update
方法期间添加子项时知道(或设置)子项的高度,则可以使用以下方法设置高度:
widget_holder.height = new_height
new_height
上面计算的总和在哪里。如果您不知道孩子的身高,您可以执行以下操作:
def adjust_height(self, box, dt):
# this does not handle padding and spacing
new_height = 0
for child in box.children:
new_height += child.height
box.height = new_height
您可以在update()
方法结束时将其称为:
Clock.schedule_once(partial(self.adjust_height, widget_holder))
推荐阅读
- mysql - MySQL Query Help for Multiple Tables
- javascript - How do I set a foreign key for a Sequelize model?
- r - 删除 r 中包含整数的列
- java - 并发文件移动访问
- java - Elasticsearch,文档中数组大小的总和
- reactjs - React Native how to use styles props
- python - How to match & replace multiple strings with regex in Python
- swift - 试图用 swift 理解 NSLayoutConstraints
- c - 与 Pthread 和互斥锁共享有界缓冲区,忙等待
- java - How to remove item from firebase list