Kivy:包含 ScrollView、StackLayout 和 Labels 的屏幕都不合适
Kivy: Screen containing ScrollView, StackLayout and Labels is all out of place
我想要一个包含 StackLayout 的屏幕。这个 StackLayout 包含几个长度从短到长的标签。 StackLayout 的全部内容也应该可以使用 ScrollView 滚动。我尝试了下面的设置,但基本上每个标签都不合适。根据我对 kivy 文档和互联网上(有点)类似问题的理解,我尝试了几种替代设置,但没有一个真正有效。
这是代码的最小工作版本:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
Window.size = (350, 600)
class RootWindow(Screen):
def __init__(self, **kwargs):
super(RootWindow, self).__init__(**kwargs)
self.searchButton = Button(text="Search",
size_hint=(1,0.8))
self.searchButton.bind(on_press=self.search)
self.add_widget(self.searchButton)
# some irrelevant code
def search(self,instance):
#here some omitted code which grabs some strings from a SQLite db and saves results in src, ingsList and steps
src = 'Lorem ipsum'
ingsList = ['Lorem', 'ipsum', 'dolor', 'sit amet']
WMan.transition.direction = 'left'
WMan.current = 'second'
# theses should be aligned at center of the screen
WMan.current_screen.title.add_widget(Label(text=src,
size_hint=(1,None)))
WMan.current_screen.ingredients.add_widget(Label(text="Ingredients:",
text_size=(self.width, None),
size_hint=(1,None),
height='30sp'))
# these should be left aligned
for i in range(0,len(ingsList)):
WMan.current_screen.ingredients.add_widget(Label(text=ingsList[i],
text_size=(self.width, None),
size_hint=(0.9,None),
height='20sp'))
# center aligned
WMan.current_screen.ingredients.add_widget(Label(text="Steps:",
text_size=(self.width, None),
size_hint=(1,None),
height='30sp'))
# this should be left aligned (or, ideally, justified)
steps = "Duis finibus risus tempor nisl scelerisque, quis facilisis augue pretium. Nullam sit amet nibh ex. Pellentesque lobortis eget ipsum a congue. Nunc luctus odio sit amet arcu interdum, id pharetra urna semper. Proin at turpis vel neque facilisis pretium ut sed massa. Phasellus elit diam, elementum at tempus non, eleifend quis libero. Integer convallis tortor eget mattis eleifend."
WMan.current_screen.ingredients.add_widget(Label(text=steps,
text_size=(self.width, None),
size_hint=(1,None),
pos_hint=(None,None),
height='10sp'
))
class SecondWindow(Screen):
def __init__(self, **kwargs):
super(SecondWindow, self).__init__(**kwargs)
self.title = StackLayout(pos_hint={"x":0.05, "top":0.9},
size_hint = (0.9,0.2))
self.add_widget(self.title)
self.ingredients = StackLayout(pos_hint={"x":0.05, "top": 0.8},
size_hint=(0.9,None),
size_hint_y=None,
orientation='lr-tb',
spacing = (0,2))
self.ingredients.bind(minimum_height = self.ingredients.setter('height'))
self.scroll = ScrollView(size_hint=(1,None),
size=(self.width, Window.height),
pos_hint={"x": 0.05, "top":0.8})
self.scroll.add_widget(self.ingredients)
self.add_widget(self.scroll)
WMan = ScreenManager()
WMan.add_widget(RootWindow(name='root'))
WMan.add_widget(SecondWindow(name='second'))
class MyApp(App):
def build(self):
return WMan
if __name__ == "__main__":
MyApp().run()
使用 kv
语言更容易解决这个问题。这是您的代码的修改版本,可以满足您的要求:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
Window.size = (350, 600)
class LeftAlignedLabel(Label):
pass
Builder.load_string('''
<LeftAlignedLabel>:
size_hint: 1, None
height: '20sp'
text_size: self.size
halign: 'left'
<SecondWindow>:
StackLayout:
id: title_stack
pos_hint: {"x":0.05, "top":0.9}
size_hint: (0.9,0.2)
Label:
id: title
size_hint: (1, None)
height: self.texture_size[0]
ScrollView:
id: scroll
size_hint: (0.9,0.7)
pos_hint: {"x": 0.05, "top":0.7}
StackLayout:
size_hint: (0.9,None)
orientation: 'lr-tb'
spacing: (0,2)
height: self.minimum_height
Label:
text: 'Ingredients:'
size_hint: (1,None)
text_size: self.size
halign: 'left'
height: '30sp'
BoxLayout:
id: ingredients
orientation: 'vertical'
size_hint: (1, None)
height: self.minimum_height
Label:
text: 'Steps:'
size_hint: (1,None)
height: '30sp'
Label:
id: steps
text_size: (self.width, None)
size_hint: (1,None)
height: self.texture_size[1] # adjusts height according to text
''')
class RootWindow(Screen):
def __init__(self, **kwargs):
super(RootWindow, self).__init__(**kwargs)
self.searchButton = Button(text="Search",
size_hint=(1,0.8))
self.searchButton.bind(on_press=self.search)
self.add_widget(self.searchButton)
# some irrelevant code
def search(self,instance):
#here some omitted code which grabs some strings from a SQLite db and saves results in src, ingsList and steps
src = 'Lorem ipsum'
ingsList = ['Lorem', 'ipsum', 'dolor', 'sit amet']
WMan.transition.direction = 'left'
WMan.current = 'second'
# theses should be aligned at center of the screen
# WMan.current_screen.title.add_widget(Label(text=src,
# size_hint=(1,None)))
WMan.current_screen.ids.title.text = src
# these should be left aligned
for i in range(0,len(ingsList)):
WMan.current_screen.ids.ingredients.add_widget(LeftAlignedLabel(text=ingsList[i]))
# this should be left aligned (or, ideally, justified)
steps = "Duis finibus risus tempor nisl scelerisque, quis facilisis augue pretium. Nullam sit amet nibh ex. Pellentesque lobortis eget ipsum a congue. Nunc luctus odio sit amet arcu interdum, id pharetra urna semper. Proin at turpis vel neque facilisis pretium ut sed massa. Phasellus elit diam, elementum at tempus non, eleifend quis libero. Integer convallis tortor eget mattis eleifend."
WMan.current_screen.ids.steps.text = steps
class SecondWindow(Screen):
pass
WMan = ScreenManager()
WMan.add_widget(RootWindow(name='root'))
WMan.add_widget(SecondWindow(name='second'))
class MyApp(App):
def build(self):
return WMan
if __name__ == "__main__":
MyApp().run()
LeftAlignedLabel
class 用于使成分列表左对齐。
此外,使用 kv
语言可以更轻松地查看有问题的结构。比如标题Label
是第一个StackLayout
中唯一的child。一般来说,如果您不打算添加额外的 children,只有一个 child 的布局可以替换为仅 child.
我想要一个包含 StackLayout 的屏幕。这个 StackLayout 包含几个长度从短到长的标签。 StackLayout 的全部内容也应该可以使用 ScrollView 滚动。我尝试了下面的设置,但基本上每个标签都不合适。根据我对 kivy 文档和互联网上(有点)类似问题的理解,我尝试了几种替代设置,但没有一个真正有效。
这是代码的最小工作版本:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
Window.size = (350, 600)
class RootWindow(Screen):
def __init__(self, **kwargs):
super(RootWindow, self).__init__(**kwargs)
self.searchButton = Button(text="Search",
size_hint=(1,0.8))
self.searchButton.bind(on_press=self.search)
self.add_widget(self.searchButton)
# some irrelevant code
def search(self,instance):
#here some omitted code which grabs some strings from a SQLite db and saves results in src, ingsList and steps
src = 'Lorem ipsum'
ingsList = ['Lorem', 'ipsum', 'dolor', 'sit amet']
WMan.transition.direction = 'left'
WMan.current = 'second'
# theses should be aligned at center of the screen
WMan.current_screen.title.add_widget(Label(text=src,
size_hint=(1,None)))
WMan.current_screen.ingredients.add_widget(Label(text="Ingredients:",
text_size=(self.width, None),
size_hint=(1,None),
height='30sp'))
# these should be left aligned
for i in range(0,len(ingsList)):
WMan.current_screen.ingredients.add_widget(Label(text=ingsList[i],
text_size=(self.width, None),
size_hint=(0.9,None),
height='20sp'))
# center aligned
WMan.current_screen.ingredients.add_widget(Label(text="Steps:",
text_size=(self.width, None),
size_hint=(1,None),
height='30sp'))
# this should be left aligned (or, ideally, justified)
steps = "Duis finibus risus tempor nisl scelerisque, quis facilisis augue pretium. Nullam sit amet nibh ex. Pellentesque lobortis eget ipsum a congue. Nunc luctus odio sit amet arcu interdum, id pharetra urna semper. Proin at turpis vel neque facilisis pretium ut sed massa. Phasellus elit diam, elementum at tempus non, eleifend quis libero. Integer convallis tortor eget mattis eleifend."
WMan.current_screen.ingredients.add_widget(Label(text=steps,
text_size=(self.width, None),
size_hint=(1,None),
pos_hint=(None,None),
height='10sp'
))
class SecondWindow(Screen):
def __init__(self, **kwargs):
super(SecondWindow, self).__init__(**kwargs)
self.title = StackLayout(pos_hint={"x":0.05, "top":0.9},
size_hint = (0.9,0.2))
self.add_widget(self.title)
self.ingredients = StackLayout(pos_hint={"x":0.05, "top": 0.8},
size_hint=(0.9,None),
size_hint_y=None,
orientation='lr-tb',
spacing = (0,2))
self.ingredients.bind(minimum_height = self.ingredients.setter('height'))
self.scroll = ScrollView(size_hint=(1,None),
size=(self.width, Window.height),
pos_hint={"x": 0.05, "top":0.8})
self.scroll.add_widget(self.ingredients)
self.add_widget(self.scroll)
WMan = ScreenManager()
WMan.add_widget(RootWindow(name='root'))
WMan.add_widget(SecondWindow(name='second'))
class MyApp(App):
def build(self):
return WMan
if __name__ == "__main__":
MyApp().run()
使用 kv
语言更容易解决这个问题。这是您的代码的修改版本,可以满足您的要求:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
Window.size = (350, 600)
class LeftAlignedLabel(Label):
pass
Builder.load_string('''
<LeftAlignedLabel>:
size_hint: 1, None
height: '20sp'
text_size: self.size
halign: 'left'
<SecondWindow>:
StackLayout:
id: title_stack
pos_hint: {"x":0.05, "top":0.9}
size_hint: (0.9,0.2)
Label:
id: title
size_hint: (1, None)
height: self.texture_size[0]
ScrollView:
id: scroll
size_hint: (0.9,0.7)
pos_hint: {"x": 0.05, "top":0.7}
StackLayout:
size_hint: (0.9,None)
orientation: 'lr-tb'
spacing: (0,2)
height: self.minimum_height
Label:
text: 'Ingredients:'
size_hint: (1,None)
text_size: self.size
halign: 'left'
height: '30sp'
BoxLayout:
id: ingredients
orientation: 'vertical'
size_hint: (1, None)
height: self.minimum_height
Label:
text: 'Steps:'
size_hint: (1,None)
height: '30sp'
Label:
id: steps
text_size: (self.width, None)
size_hint: (1,None)
height: self.texture_size[1] # adjusts height according to text
''')
class RootWindow(Screen):
def __init__(self, **kwargs):
super(RootWindow, self).__init__(**kwargs)
self.searchButton = Button(text="Search",
size_hint=(1,0.8))
self.searchButton.bind(on_press=self.search)
self.add_widget(self.searchButton)
# some irrelevant code
def search(self,instance):
#here some omitted code which grabs some strings from a SQLite db and saves results in src, ingsList and steps
src = 'Lorem ipsum'
ingsList = ['Lorem', 'ipsum', 'dolor', 'sit amet']
WMan.transition.direction = 'left'
WMan.current = 'second'
# theses should be aligned at center of the screen
# WMan.current_screen.title.add_widget(Label(text=src,
# size_hint=(1,None)))
WMan.current_screen.ids.title.text = src
# these should be left aligned
for i in range(0,len(ingsList)):
WMan.current_screen.ids.ingredients.add_widget(LeftAlignedLabel(text=ingsList[i]))
# this should be left aligned (or, ideally, justified)
steps = "Duis finibus risus tempor nisl scelerisque, quis facilisis augue pretium. Nullam sit amet nibh ex. Pellentesque lobortis eget ipsum a congue. Nunc luctus odio sit amet arcu interdum, id pharetra urna semper. Proin at turpis vel neque facilisis pretium ut sed massa. Phasellus elit diam, elementum at tempus non, eleifend quis libero. Integer convallis tortor eget mattis eleifend."
WMan.current_screen.ids.steps.text = steps
class SecondWindow(Screen):
pass
WMan = ScreenManager()
WMan.add_widget(RootWindow(name='root'))
WMan.add_widget(SecondWindow(name='second'))
class MyApp(App):
def build(self):
return WMan
if __name__ == "__main__":
MyApp().run()
LeftAlignedLabel
class 用于使成分列表左对齐。
此外,使用 kv
语言可以更轻松地查看有问题的结构。比如标题Label
是第一个StackLayout
中唯一的child。一般来说,如果您不打算添加额外的 children,只有一个 child 的布局可以替换为仅 child.