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

huangapple go评论59阅读模式
英文:

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

问题

以下是您要翻译的代码部分:

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()
英文:

I have a following problem: I need to write an app, where I will show proper answers for every question. I wrote with kivy some code and I'm struggling with one thing. I created a page. There is a button for showing answers, but after one press I only see a part of my answers and I can't scroll. But, when I press a button second time, everything is good. Could you tell me why is that? How to repair it? I would like to see all answers after pressing a button once and be able to scroll.

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

答案1

得分: 1

I think your widget heights are not updating correctly, and to correct that requires doing some binding. Since the 'kv' language automatically does bindings, I have provided an answer that uses '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()

I believe the two instances of size_hint_y: None and the corresponding height rules are the key.

Note that I also changed:

ScrollableLabel.update(self.scroll, lines)

to:

self.scroll.update(lines)
英文:

I think your widget heights are not updating correctly, and to correct that requires doing some binding. Since the 'kv' language automatically does bindings, I have provided an answer that uses '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(&#39;graphics&#39;, &#39;resizable&#39;, True)
class MyApp(App):
def build(self):
self.screen_manager = ScreenManager()
self.answers = Answers()
screen = Screen(name = &quot;Answers&quot;)
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 = &quot;Answers: &quot;, font_size = 40)
self.add_widget(self.label)
self.button = Button(text=&quot;Show answers&quot;)
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(&quot;text.txt&quot;, &quot;r&quot;)
lines = f.readlines()
self.scroll.update(lines)
myapp.screen_manager.current = &quot;Answers&quot;
class ScrollableLabel(ScrollView):
def update(self, lines):
self.ids.lines.text = &#39;\n&#39;
for i in range(len(lines)):
self.ids.lines.text += &#39;\n &#39; +str(i+1) + &quot;. &quot; + lines[i]
Builder.load_string(&#39;&#39;&#39;
&lt;ScrollableLabel&gt;:
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
&#39;&#39;&#39;)
f = open(&quot;text.txt&quot;, &#39;a+&#39;)
for i in range(30):
f.write(&quot;Important text \n&quot;)
f.close()
myapp = MyApp()
myapp.run()

I believe the two instances of size_hint_y: None and the corresponding height rules are the key.

Note that I also changed:

ScrollableLabel.update(self.scroll, lines)

to:

self.scroll.update(lines)

huangapple
  • 本文由 发表于 2020年1月6日 23:53:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/59615116.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定