首页 > 解决方案 > Kivy Scrollview 自动滚动到新文本。防止向上滚动

问题描述

对于我实际上非常简单的 Python Kivy 问题,我真的真的需要一些帮助!我有一个 Kivy 滚动视图,想通过单击按钮添加一些文本。每次单击后,滚动视图应自动滚动到新的文本行。但由于某种原因,它只能每秒钟运行一次。文本在跳转到顶部和跳转到新文本行之间切换。当文本位于底部并且您手动滚动(或只需单击滚动视图字段)时,文本会跳到顶部。我希望能够手动滚动,但是如果不单击“添加文本”,文本不应该跳转。但是,当单击“添加文本”时,它应该按照描述滚动到新的文本行。

import kivy
from kivy.config import Config
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 ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.scrollview import ScrollView
from kivy.clock import mainthread
import threading

kivy.require("2.0.0")
Config.set('kivy', 'keyboard_mode', 'systemandmulti')

class MainMenu(GridLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.cols = 1
        self.rows = 3
        
        self.infowindow = ScrollableInfo(height=Window.size[1]*0.8, size_hint_y=None)
        self.add_widget(self.infowindow)

        self.addtextbutton = Button(text="Add Text")
        self.addtextbutton.bind(on_press=self.add_text_thread)
        self.add_widget(self.addtextbutton)

    def addtext(self, *_):
        self.infowindow.update_scrollview(f"This is some new Text")
     

    def add_text_thread(self, *args):
        threading.Thread(target=self.addtext, daemon=True).start()



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

        self.text_history = Label(size_hint_y=None, markup=True)

        self.layout.add_widget(self.text_history)

    @mainthread
    def update_scrollview(self, newinfo):
        self.text_history.text += '\n' + newinfo
        
        self.layout.height = self.text_history.texture_size[1]+15
        self.text_history.height = self.text_history.texture_size[1]
        self.text_history.text_size = (self.text_history.width*0.98, None)

        self.scroll_y = 0

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

        self.mainmenu_page = MainMenu()
        screen = Screen(name="MainMenu")
        screen.add_widget(self.mainmenu_page)
        self.screen_manager.add_widget(screen)

        return self.screen_manager

if __name__ == "__main__":
    counting_app = Textadding()
    counting_app.run()

非常感谢您的帮助!

标签: pythonbuttonkivyscrollviewautoscroll

解决方案


如果我理解正确,你想要这样的东西。你的代码有很多bug,很麻烦,所以我完全重写了。我也不建议在辅助线程中更改UIkivy == 2.1.0dev0 (添加小部件、播放动画),这是一种不好的做法,并且可能会导致错误。

from kivy.app import App
from kivy.lang import Builder

kv = """
Screen:
    BoxLayout:
        spacing: 10
        orientation: "vertical"
        
        ScrollView:
            id: scroll_view
            always_overscroll: False
            BoxLayout:
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'
                Label:
                    id: label
                    size_hint: None, None
                    size: self.texture_size 

        Button:
            text: "Add Text"
            size_hint_y: 0.2
            on_release: app.add_text()
        
"""


class TextAdding(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.text_counter = 0

    def build(self):
        return Builder.load_string(kv)

    def add_text(self):
        self.root.ids.label.text += f"Some text {self.text_counter}\n"
        self.text_counter += 1
        self.root.ids.scroll_view.scroll_y = 0


if __name__ == "__main__":
    TextAdding().run()

推荐阅读