python - kivy 中的属性绑定(bind)和样式问题

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

目标
我有一个带有属性 c_description 的小部件类。我需要能够为这个继承 c_description 作为文本的小部件创建和添加标签(或其他类型的小部件)。对 c_description 的更改会传播到标签的文本。我需要能够使用函数运行此标签的创建/添加。
我基本上需要做的正是this other question正在询问。


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

这是 other script在将其 text 属性绑定(bind)到 c_description 失败后,我在其中动态创建并添加了一个新的小部件。
如果我运行它,我会得到如下所示的结果。 No Text or Formatting

标签的文本是 ""而不是 c_description 的内容,所以这是一个问题。 但是,如果我删除属性绑定(bind)语句并将 c_label = StretchingLabel() 更改为 c_label = StretchingLabel(pos=self.pos, width=self.width, text=self.c_description) 我们至少应该能够看到一个成功的属性绑定(bind)是什么样子的。
当我这样做时,结果看起来像这样。 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

Why does self.bind(c_description=c_label.setter('text')) not work? The label is being created, but it's not getting the text from c_description. What am I doing wrong?

回答

你已经得到了正确的代码,

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

绑定(bind)过程不会立即更新 text . text只会在 c_description 时改变改变了。

例子

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

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

注意:-kv 文件

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

主.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

Why is the formatting wrong on the created label? I passed the same properties in the kv code that I did in makeLabel(). And I need to be able to do this properly with the makeLabel() function.

根本原因

问题是由于 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

关于python - kivy 中的属性绑定(bind)和样式问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57050377/

相关文章:

Python向图像添加噪声破坏PNG

python-3.x - 为Python 3和PyQt构建可执行文件

ios - 当一个属性是只读的时候,copy 和 nonatomic 就没有意义了吗?

javascript - javascript在spring应用程序中访问属性文件中的值的最佳方式

objective-c - iOS 在使用实例变量或 getter 方法时

python - Tkinter 标签图像设置不起作用

python - 有没有办法更新Python字典的值,但如果键不存在则不添加键?

python - Pyspark:使用 udf 根据另一个数据框中的值向数据框中添加新列

python - 在 Python 中构造 "complex"数据结构的最佳方法

python - 一个 PYTHON 程序,从数字文件中获取输入并计算平均值