Kivy: Экран, содержащий ScrollView, StackLayout и Labels, неуместен - PullRequest
0 голосов
/ 09 мая 2020

Я пытаюсь получить экран, содержащий StackLayout. Этот StackLayout содержит несколько ярлыков от короткой до длинной. Все содержимое StackLayout также должно прокручиваться с помощью ScrollView. Я пробовал установку ниже, но в основном каждый ярлык неуместен. Я попробовал несколько альтернативных настроек, основанных на моем понимании документации kivy и (в некоторой степени) похожих вопросов по inte rnet, но ни один из них не работал.

Вот минимальная рабочая версия кода:

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

1 Ответ

0 голосов
/ 09 мая 2020

Это проще решить, используя язык 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 используется для выравнивания списка ингредиентов по левому краю.

Кроме того, с помощью kv язык облегчает поиск сомнительных структур. Например, заголовок Label является единственным дочерним элементом первого StackLayout. Как правило, если вы не планируете добавлять дополнительных дочерних элементов, макет с одним дочерним элементом может быть заменен только дочерним элементом.

...