首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Kivy的ScrollView中正确创建长文本标签?

如何在Kivy的ScrollView中正确创建长文本标签?
EN

Stack Overflow用户
提问于 2014-07-04 04:31:59
回答 3查看 1.7K关注 0票数 0

我试图创建MWE来演示我的问题,但最终我对此更加困惑。

我想创建一个有几个小部件的应用程序。其中一个小工具将持有长文本,我预计将跨越约3行。我希望包含此文本的标签增加其高度以适应文本大小。

这就是我到目前为止所得到的

代码语言:javascript
复制
    layout = BoxLayout(orientation='horizontal')
    subLayout = TwoLabelCombo()
    subLayout.label1.text = ('foo:')
    subLayout.label2.text = 'bar'*50
    subLayout.label2.width = int(Window.width*0.8)
    subLayout.label2.text_size = [subLayout.label2.width,None]
    subLayout.label2.size_hint_y = None
    subLayout.label2.height = subLayout.label2.texture_size[1]
    subLayout.height = subLayout.label2.texture_size[1]
    layout.height = subLayout.height

TwoLabelCombo是方向设置为水平的BoxLayout,它与size_hint_x设置为0.2和0.8的标签保持一致。layout在应用程序中有一整行文字,其前后的布局类似。文本确实跨越了几行,但是布局不会随着文本而更新,因此与其他小部件的重叠也不会更新。打印texture_size时,我发现它的高度是0。如何获得合适的文本大小?

EN

回答 3

Stack Overflow用户

发布于 2014-07-04 05:55:18

所以这里有两个问题。首先,根据内容调整Label大小的问题。

通过基于texture_size分配height,您走上了正确的道路。但问题是,当您第一次创建Label时,纹理尚未渲染,因此您无法知道大小。关键是使用property bindings -然后height将在每次texture_size更改时更新

因此,在the kv language (在Kivy中定义UI的首选方式)中:

代码语言:javascript
复制
Label:
    text: 'some really really really long text here'
    size_hint_y: None
    height: self.texture_size[1]
    text_size: self.width, None

在kv中引用属性时,会自动绑定这些属性。但您可以在Python中执行类似的操作:

代码语言:javascript
复制
lbl = Label(text='some really really really long text here',
            size_hint_y=None)
lbl.bind(texture_size=lambda instance, value: setattr(instance, 'height', value[1]))
lbl.bind(width=lambda instance, value: setattr(instance, 'text_size', (value, None)))

第二,存在包含BoxLayout的问题。即使将这些Label设置为正确的大小,它们所在的BoxLayout仍将正常布局。这是BoxLayout的一个临时替代品,它会根据其子对象的大小调整自身的大小(当适当设置size_hint时):

代码语言:javascript
复制
class CollapsingBoxLayout(BoxLayout):
    def __init__(self, **kwargs):
        super(CollapsingBoxLayout, self).__init__(**kwargs)
        self._trigger_update_size = Clock.create_trigger(self._update_size)

    def on_children(self, *_):
        for c in self.children:
            c.bind(size=self._trigger_update_size)
        self._update_size()

    def _update_size(self, *_):
        if self.size_hint_y is None:
            self.height = max(c.height for c in self.children) if self.children else 0
        if self.size_hint_x is None:
            self.width = max(c.width for c in self.children) if self.children else 0

最后,给出一个完整的工作示例:

代码语言:javascript
复制
import kivy
kivy.require('1.8.0')

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

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label

class CollapsingBoxLayout(BoxLayout):
    def __init__(self, **kwargs):
        super(CollapsingBoxLayout, self).__init__(**kwargs)
        self._trigger_update_size = Clock.create_trigger(self._update_size)

    def on_children(self, *_):
        for c in self.children:
            c.bind(size=self._trigger_update_size)
        self._trigger_update_size()

    def _update_size(self, *_):
        if self.size_hint_y is None:
            self.height = max(c.height for c in self.children) if self.children else 0
        if self.size_hint_x is None:
            self.width = max(c.width for c in self.children) if self.children else 0

root = Builder.load_string('''
BoxLayout:
    orientation: 'vertical'
    CollapsingBoxLayout:
        size_hint_y: None

        canvas.before:
            Color:
                rgba: 1, 0, 0, 0.2
            Rectangle:
                pos: self.pos
                size: self.size

        Label:
            text: 'Paragraph 1'
            size_hint_x: 0.2
            size_hint_y: None
            height: self.texture_size[1]
            text_size: self.width, None
        Label:
            canvas.before:
                Color:
                    rgba: 0, 1, 0, 0.2
                Rectangle:
                    pos: self.pos
                    size: self.size
            size_hint_x: 0.8
            text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sollicitudin dignissim orci. Pellentesque laoreet magna quis augue dictum fringilla. Vivamus nec adipiscing nunc. Aliquam pharetra auctor justo vel rutrum. Sed sodales nulla sed odio fermentum, vel pulvinar nibh hendrerit. Phasellus a volutpat leo. Donec id hendrerit velit. Curabitur eget suscipit neque, nec tincidunt nulla. Donec feugiat, urna quis porttitor aliquet, nibh est laoreet ligula, vitae vestibulum leo purus quis ante. Maecenas magna nisi, molestie eu ipsum quis, tempor tempor turpis. Vivamus a fringilla enim. Quisque aliquam elit tortor, nec mollis tellus facilisis accumsan. Phasellus sagittis commodo mauris in vestibulum. Mauris sed ultrices enim.'
            size_hint_y: None
            height: self.texture_size[1]
            text_size: self.width, None

    CollapsingBoxLayout:
        size_hint_y: None

        canvas.before:
            Color:
                rgba: 0, 0, 1, 0.2
            Rectangle:
                pos: self.pos
                size: self.size

        Label:
            text: 'Paragraph 2'
            size_hint_x: 0.2
            size_hint_y: None
            height: self.texture_size[1]
            text_size: self.width, None
        Label:
            canvas.before:
                Color:
                    rgba: 0, 1, 0, 0.2
                Rectangle:
                    pos: self.pos
                    size: self.size
            size_hint_x: 0.8
            text: 'Duis egestas dui lobortis ante rutrum, nec consectetur arcu sollicitudin. Phasellus ut felis facilisis, eleifend odio malesuada, placerat odio. Etiam convallis non mi at tempor. Nunc gravida est magna, a hendrerit nulla condimentum a. Proin tristique velit quis dui convallis, vitae sodales nunc condimentum. In sollicitudin eros augue, sit amet blandit neque accumsan eu. Mauris non risus at nisl vestibulum dignissim quis non arcu. Integer ullamcorper felis eu neque viverra placerat. Vivamus magna quam, porta ac tincidunt a, imperdiet sed purus. Phasellus tempus ac neque vel accumsan. Pellentesque ligula justo, auctor eget aliquet ultricies, volutpat scelerisque ligula. Maecenas dictum velit id neque rhoncus fermentum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur dictum enim nisl, ut elementum lectus viverra sit amet. Praesent vel tempor risus, at congue turpis. Praesent in justo lobortis, gravida lacus id, facilisis orci.'
            size_hint_y: None
            height: self.texture_size[1]
            text_size: self.width, None
''')

class TestApp(App):
    def build(self):
        lbl = Label(text=('hello this is some long long text! ' * 10), size_hint_y=None)
        lbl.bind(texture_size=lambda instance, value: setattr(instance, 'height', value[1]))
        lbl.bind(width=lambda instance, value: setattr(instance, 'text_size', (value, None)))
        root.add_widget(lbl)
        return root

if __name__ == '__main__':
    TestApp().run()
票数 0
EN

Stack Overflow用户

发布于 2014-07-04 06:00:30

问题可能是,在实际生成和显示纹理之前,texture_size不会更新,这可能不会在方法结束时发生(但可能在下一帧之前发生)。出于这个原因,您通常希望绑定到属性,而不是获取它们的瞬时值。

你的整个规则可以用kv语言更简单地表达出来,而且有了这个免费的附加功能(我正在猜测你在文章中没有包含的小部件添加,但你应该看到大意)。

:size_hint_y:无高度: label2.texture_size1 Label:# label1 text:'foo:‘Label:# label2 id: label2 text:'bar’* 50 width: int(Window.width*0.8) #通过布局text_size: self.width,None可以更好地完成此操作

我还稍微改变了设置,设置了根BoxLayout的高度,而不是标签的高度,我认为这样会更好。

当然,您也可以在python中使用widget的bind方法重新创建相关的绑定(这是kv在幕后做的事情),但它更冗长。

我有一段视频涵盖了其中的一些内容,还有其他一些东西,here

票数 0
EN

Stack Overflow用户

发布于 2016-12-29 00:46:27

以防其他任何人正在寻找包含BoxLayout或GridLayout的自扩展ScrollView的解决方案,作为参考,它实际上是自扩展的小部件。有了Ryan P的回答,我得到了大部分的答案;但后来我意识到他是在解决一个非常具体的用例,这就是为什么他使用max函数。我需要的是一个随着新窗口小部件的添加而扩展的框。所以我简单地将他的_update_size()代码修改为:

代码语言:javascript
复制
def _update_size(self, *_):
    temp_height = 0
    if self.size_hint_y is None:
        for c in self.children:
            temp_height += c.height
        self.height = temp_height + 10  # Add a buffer to the bottom to prevent text clipping.
    if self.size_hint_x is None:
        self.width = max(c.width for c in self.children) if self.children else 0

有几点注意事项,我没有使用宽度部分,因为对于我的用例来说,这样做是有意义的,但也可以用类似的方式进行修改。

此外,使用此方法更改标签小部件的大小的最简单方法是使用remove_widget()删除小部件,然后使用kivy.lang.Builder.load_string()创建一个新的小部件,并将该小部件添加到您的自展开/折叠BoxLayout或GridLayout中,它将重新计算它的大小,并相应地调整滚动视图的滚动距离。不要忘记size_hint_y: None,它必须等于none,否则将不会应用任何更新。

希望这是足够的细节来帮助任何人通过边缘情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24562841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档