为什么我必须点击两次才能滚动? kivy 中的可滚动标签,python

Why I have to click twice to scroll? Scrollable Label in kivy, python

我有以下问题:我需要编写一个应用程序,我会在其中显示每个问题的正确答案。我用 kivy 写了一些代码,但我正在为一件事而苦苦挣扎。我创建了一个页面。有一个用于显示答案的按钮,但按一下后我只能看到我的部分答案并且无法滚动。但是,当我第二次按下按钮时,一切都很好。你能告诉我这是为什么吗?如何修复?我想在按下按钮一次后看到所有答案并能够滚动。

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.scrollview import ScrollView
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.config import Config
Config.set('graphics', 'resizable', True)
import os
import sys

class MyApp(App):
    def build(self):
        self.screen_manager = ScreenManager()

        self.answers = Answers()
        screen = Screen(name = "Answers")
        screen.add_widget(self.answers)
        self.screen_manager.add_widget(screen)

        return self.screen_manager

class Answers(GridLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.rows = 3

        self.label = Label(text = "Answers: ", font_size = 40)
        self.add_widget(self.label)

        self.button = Button(text="Show answers")
        self.button.bind(on_press=self.showanswers)
        self.add_widget(self.button)

        self.scroll = ScrollableLabel(height = Window.size[1]*0.75, size_hint_y = None)
        self.add_widget(self.scroll)


    def showanswers(self, instance):
        f = open("text.txt", "r")
        lines = f.readlines()

        ScrollableLabel.update(self.scroll, lines)
        myapp.screen_manager.current = "Answers"


class ScrollableLabel(ScrollView):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.layout = GridLayout(cols = 1,  size_hint_y = None)
        self.add_widget(self.layout)

        self.lines = Label(size_hint_x = 1, size_hint_y = None, text_size = (self.width, None))

        self.scroll_to_point = Label()
        self.scroll_to_point.bind(texture_size=self.scroll_to_point.setter('size'))

        self.layout.add_widget(self.lines)
        self.layout.add_widget(self.scroll_to_point)


    def update(self, lines):
        self.lines.text = '\n'

        for i in range(len(lines)):
            self.lines.text += '\n ' +str(i+1) + ". " + lines[i]

        self.layout.height = self.lines.texture_size[1]
        self.lines.height = self.lines.texture_size[1]
        self.lines.text_size = (self.lines.width*0.75, None)

        self.scroll_to(self.scroll_to_point)

f = open("text.txt", 'a+')
for i in range(30):
    f.write("Important text \n")
f.close()

myapp = MyApp()
myapp.run()

我认为您的小部件高度没有正确更新,要更正它需要进行一些绑定。由于 'kv' 语言会自动进行绑定,因此我提供了一个使用 'kv':

的答案
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window
from kivy.config import Config
Config.set('graphics', 'resizable', True)

class MyApp(App):
    def build(self):
        self.screen_manager = ScreenManager()

        self.answers = Answers()
        screen = Screen(name = "Answers")
        screen.add_widget(self.answers)
        self.screen_manager.add_widget(screen)

        return self.screen_manager

class Answers(GridLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.rows = 3

        self.label = Label(text = "Answers: ", font_size = 40)
        self.add_widget(self.label)

        self.button = Button(text="Show answers")
        self.button.bind(on_press=self.showanswers)
        self.add_widget(self.button)

        self.scroll = ScrollableLabel(height = Window.size[1]*0.75, size_hint_y = None)
        self.add_widget(self.scroll)


    def showanswers(self, instance):
        f = open("text.txt", "r")
        lines = f.readlines()

        self.scroll.update(lines)
        myapp.screen_manager.current = "Answers"


class ScrollableLabel(ScrollView):

    def update(self, lines):
        self.ids.lines.text = '\n'
        for i in range(len(lines)):
            self.ids.lines.text += '\n ' +str(i+1) + ". " + lines[i]

Builder.load_string('''
<ScrollableLabel>:
    size_hint_y: None
    GridLayout:
        cols: 1
        size_hint_y: None
        height: self.minimum_height  # adjust height to handle the Label
        Label:
            id: lines
            size_hint_y: None
            height: self.texture_size[1]  # set height based on text
''')

f = open("text.txt", 'a+')
for i in range(30):
    f.write("Important text \n")
f.close()

myapp = MyApp()
myapp.run()

我相信 size_hint_y: None 的两个实例和相应的 height 规则是关键。

注意我也改了:

ScrollableLabel.update(self.scroll, lines)

至:

self.scroll.update(lines)