猕猴桃中的属性绑定和样式问题

时间:2019-07-16 05:09:03

标签: python python-3.x properties kivy kivy-language

目标
我有一个具有属性c_description的小部件类。我需要能够创建标签并将标签(或其他类型的小部件)添加到继承c_description作为文本的小部件中。对c_description的更改会传播到标签的文本。我需要能够使用功能来运行此标签的创建/添加。
我基本上需要做this other question的要求。


我做了什么,遇到了什么问题
我格式化了这个标签类StretchingLabel以适应其内容。我有一个script in kivy,显示了我希望它如何工作。 最终结果应如下所示。 This is how the result should look

这是other script,在将其text属性未成功绑定到c_description后,我在其中动态创建并添加了新的窗口小部件。
如果运行该命令,将得到如下所示的结果。 No Text or Formatting

标签的文本是“”而不是c_description的内容,所以这是一个问题。 但是,如果我删除属性绑定语句,并将c_label = StretchingLabel()更改为c_label = StretchingLabel(pos=self.pos, width=self.width, text=self.c_description),我们应该至少能够看到成功的属性绑定的外观。
当我这样做时,结果看起来像这样。 GoodTextBadFormatting 这不是我想要的。我希望它看起来像第一张照片。

我的代码

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.clock import Clock
    from kivy.uix.widget import Widget
    from kivy.uix.label import Label
    from kivy.uix.boxlayout import BoxLayout
    from kivy.properties import StringProperty
    from kivy.uix.textinput import TextInput

    Builder.load_string('''
    <StretchingLabel>:
        size_hint_y: None
        text_size: self.width, None
        height: self.texture_size[1]
        group: 'test'
        canvas.before:
            Color:
                rgba: .7, .7, .7, 1
            Rectangle:
                pos: self.pos
                size: self.size

    <MyLabelFrame>:
        id: xLabel

    <ContainerBox>:
        orientation: 'horizontal'
        Button:
            text: 'h1'
            group: 'test'
        BoxLayout:
            orientation: 'vertical'
            size: root.size
            pos: root.pos
            Label:
                text: 'Description'
                size_hint_y: None
                height: 30
                bold: True
            MyLabelFrame:
            Label:
    ''')

    class StretchingLabel(Label):
        def __init__(self, **kwargs):
            super(StretchingLabel, self).__init__(**kwargs)
            #This is for debugging
            Clock.schedule_once(lambda dt: print("StretchingLabel.init(): ", self.text), timeout=0.01)
        def on_double_click(self, instance, p_ignoreme):
            #This is also for debugging
            print("StretchingLabel.on_double_click():", self.text)

    class MyLabelFrame(Widget):
        c_description = StringProperty(
            'Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n\nProin vitae turpis ornare urna elementum pharetra non et tortor. Curabitur semper mattis viverra. \nPellentesque et lobortis purus, eu ultricies est. Nulla varius ac dolor quis mattis. Pellentesque vel accumsan tellus. Donec a nunc urna. Nulla convallis dignissim leo, tempor sagittis orci sollicitudin aliquet. Duis efficitur ex vel auctor ultricies. Etiam feugiat hendrerit mauris suscipit gravida. Quisque lobortis vitae ligula eget tristique. Nullam a nulla id enim finibus elementum eu sit amet elit.')

        def __init__(self, **kwargs):
            super(MyLabelFrame, self).__init__(**kwargs)
            Clock.schedule_once(lambda dt: self.makeLabel(), timeout=0.01)

        def makeLabel(self):
            c_label = StretchingLabel()
            #HERE! This vvv does not seem to work for some reason.
            self.bind(pos=c_label.setter('pos'), width=c_label.setter('width'), c_description=c_label.setter('text'))
            #This vvv didn't work either.
            #c_label.bind(pos=self.setter('pos'), width=self.setter('width'), text=self.setter('c_description'))
            self.add_widget(c_label)

    class ContainerBox(BoxLayout):
        def __init__(self, **kwargs):
            super(ContainerBox, self).__init__(**kwargs)

    class Nested2App(App):
        def build(self):
            return ContainerBox()

    if __name__ == '__main__':
        Nested2App().run()

我对您的问题

  1. 为什么self.bind(c_description=c_label.setter('text'))不起作用?标签已创建,但是没有从c_description获取文本。我在做什么错了?
  2. 为什么在创建的标签上格式错误?我在kv代码中传递了与makeLabel()中相同的属性。而且我需要能够使用makeLabel()函数正确地做到这一点。

注意

我看到another question here遇到了与我完全相同的问题(没有格式问题),但是由于某种原因,答案对我不起作用。

1 个答案:

答案 0 :(得分:0)

问题1

  

为什么self.bind(c_description = c_label.setter('text'))不起作用?的   标签正在创建,但没有从中获取文本   c_description。我在做什么错了?

答案

您具有正确的代码,

self.bind(pos=c_label.setter('pos'), width=c_label.setter('width'), c_description=c_label.setter('text'))

绑定过程不会立即更新texttext仅在c_description更改时更改。

示例

以下示例说明了以下内容:

  1. 最初显示一个空标签
  2. 更改后显示c_descripton,但显示为窗口小部件的默认pos=[0,0]width=100
  3. 最大化窗口,并且c_descriptionpos已更改,因此width显示在正确的位置。

注意:-kv文件

color: 0, 0, 0, 1 # black colour text添加到类规则<StretchingLabel>:中,因为文本不可见。这是因为背景颜色是白色,而Label文本的默认颜色也是白色。

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty

Builder.load_string('''
<StretchingLabel>:
    color: 0, 0, 0, 1   # black color text    

    size_hint_y: None
    text_size: self.width, None
    height: self.texture_size[1]   
    group: 'test'

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

<MyLabelFrame>:
    id: xLabel

<ContainerBox>:
    orientation: 'horizontal'
    Button:
        text: 'h1'
        group: 'test'

    BoxLayout:
        orientation: 'vertical'
        size: root.size
        pos: root.pos

        Label:
            text: 'Description'
            size_hint_y: None
            height: 30
            bold: True

        MyLabelFrame:

        Label:
''')


class StretchingLabel(Label):

    def __init__(self, **kwargs):
        super(StretchingLabel, self).__init__(**kwargs)
        # This is for debugging
        Clock.schedule_once(lambda dt: print("StretchingLabel.init(): ", self.text), timeout=0.01)

    def on_double_click(self, instance, p_ignoreme):
        # This is also for debugging
        print("StretchingLabel.on_double_click():", self.text)


class MyLabelFrame(Widget):
    c_description = StringProperty(
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n\nProin vitae turpis ornare urna elementum pharetra non et tortor. Curabitur semper mattis viverra. \nPellentesque et lobortis purus, eu ultricies est. Nulla varius ac dolor quis mattis. Pellentesque vel accumsan tellus. Donec a nunc urna. Nulla convallis dignissim leo, tempor sagittis orci sollicitudin aliquet. Duis efficitur ex vel auctor ultricies. Etiam feugiat hendrerit mauris suscipit gravida. Quisque lobortis vitae ligula eget tristique. Nullam a nulla id enim finibus elementum eu sit amet elit.')

    def __init__(self, **kwargs):
        super(MyLabelFrame, self).__init__(**kwargs)
        Clock.schedule_once(lambda dt: self.makeLabel(), timeout=0.8)

    def makeLabel(self):
        c_label = StretchingLabel()
        self.bind(pos=c_label.setter('pos'), width=c_label.setter('width'), c_description=c_label.setter('text'))
        self.add_widget(c_label)

        Clock.schedule_once(lambda dt: self.chg_text(), 1)

    def chg_text(self):
        self.c_description = 'Updated: ...' + self.c_description


class ContainerBox(BoxLayout):
    def __init__(self, **kwargs):
        super(ContainerBox, self).__init__(**kwargs)


class Nested2App(App):
    def build(self):
        return ContainerBox()


if __name__ == '__main__':
    Nested2App().run()

输出

应用已启动 App staarted

c_description已更新 c_description updated

最大化和最小化窗口 Maximised and Minimized Window

问题2

  

为什么在创建的标签上格式错误?我通过了相同的   我在makeLabel()中执行的kv代码中的属性。我需要   能够使用makeLabel()函数正确地做到这一点。

根本原因

问题是由于Kivy的样式尚未完成。

解决方案

timeout的值至少增加0.8秒。此值会有所不同,即取决于您计算机的速度。

摘要

    def __init__(self, **kwargs):
        super(MyLabelFrame, self).__init__(**kwargs)
        Clock.schedule_once(lambda dt: self.makeLabel(), timeout=0.8)

    def makeLabel(self):
        c_label = StretchingLabel(pos=self.pos, width=self.width, text=self.c_description)
        self.add_widget(c_label)

输出

Result