属性 kivy 中的绑定和样式问题
Problems with property binding and styling in kivy
目标
我有一个带有 属性 c_description
的小部件 class。我需要能够创建标签(或其他类型的小部件)并将其添加到继承 c_description
作为文本的小部件。 c_description
的更改会传播到标签的文本。我需要能够 运行 这个 creation/addition 这个标签的功能。
我基本上需要完全按照 的要求去做。
我做了什么,我运行遇到了什么问题
我格式化了这个标签 class StretchingLabel
以适应它的内容。我有一个 script in kivy 显示我希望它如何工作。
最终结果应该是这样的。
这是 other script,我在其中 text
属性 绑定到 c_description
失败后动态创建并添加了一个新的小部件。
如果我 运行 我得到的结果看起来像这样。
标签的文本是“”而不是 c_description
的内容,所以这是一个问题。
但是如果我删除 属性 绑定语句并将 c_label = StretchingLabel()
更改为 c_label = StretchingLabel(pos=self.pos, width=self.width, text=self.c_description)
我们至少应该能够看到成功的 属性 绑定是什么样子的。
当我这样做时,结果看起来像这样。
这不是我想要的。我希望它看起来像第一张图片。
我的代码
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()
我想问你的问题
- 为什么
self.bind(c_description=c_label.setter('text'))
不起作用?正在创建标签,但未从 c_description
获取文本。我做错了什么?
- 为什么创建的标签格式不对?我在 kv 代码中传递了与
makeLabel()
中相同的属性。我需要能够使用 makeLabel()
函数正确执行此操作。
注
我看到 遇到了与我完全相同的问题(没有格式问题),但出于某种原因,答案对我不起作用。
问题 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'))
绑定进程不会立即更新 text
。 text
只会在 c_description
改变时改变。
例子
以下示例说明了以下内容:
- 最初显示空标签
- 在更改后显示
c_descripton
,但在小部件的默认值 pos=[0,0]
和 width=100
- 最大化 window 和
c_description
显示在正确的位置,因为 pos
和 width
已更改。
注:-kv文件
已将 color: 0, 0, 0, 1 # black colour text
添加到 class 规则中,<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()
输出
应用已启动
c_description
已更新
最大化和最小化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)
输出
目标
我有一个带有 属性 c_description
的小部件 class。我需要能够创建标签(或其他类型的小部件)并将其添加到继承 c_description
作为文本的小部件。 c_description
的更改会传播到标签的文本。我需要能够 运行 这个 creation/addition 这个标签的功能。
我基本上需要完全按照
我做了什么,我运行遇到了什么问题
我格式化了这个标签 class StretchingLabel
以适应它的内容。我有一个 script in kivy 显示我希望它如何工作。
最终结果应该是这样的。
这是 other script,我在其中 text
属性 绑定到 c_description
失败后动态创建并添加了一个新的小部件。
如果我 运行 我得到的结果看起来像这样。
标签的文本是“”而不是 c_description
的内容,所以这是一个问题。
但是如果我删除 属性 绑定语句并将 c_label = StretchingLabel()
更改为 c_label = StretchingLabel(pos=self.pos, width=self.width, text=self.c_description)
我们至少应该能够看到成功的 属性 绑定是什么样子的。
当我这样做时,结果看起来像这样。
我的代码
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()
我想问你的问题
- 为什么
self.bind(c_description=c_label.setter('text'))
不起作用?正在创建标签,但未从c_description
获取文本。我做错了什么? - 为什么创建的标签格式不对?我在 kv 代码中传递了与
makeLabel()
中相同的属性。我需要能够使用makeLabel()
函数正确执行此操作。
注
我看到
问题 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'))
绑定进程不会立即更新 text
。 text
只会在 c_description
改变时改变。
例子
以下示例说明了以下内容:
- 最初显示空标签
- 在更改后显示
c_descripton
,但在小部件的默认值pos=[0,0]
和width=100
- 最大化 window 和
c_description
显示在正确的位置,因为pos
和width
已更改。
注:-kv文件
已将 color: 0, 0, 0, 1 # black colour text
添加到 class 规则中,<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()
输出
应用已启动
c_description
已更新
最大化和最小化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)