I'm working on a simple Kivy Popup and I'm confused as to why I can't reference my class variable, 'self.text_1', from within the constructor of the Popup class, but I can do so with the variable 'self.title'.
First, I'll start with the ubiquitous, "I'm new to Python and Kivy, so perhaps I'm just missing something obvious, but I'm at a loss."
I've tried to find answers, but nothing so far has seemed to cover this topic, at least in a way that I can understand and draw the connection. Below is my problem and some simplified code for demonstration.
From within the kv file > Label widget > text, I can refer to 'text_1' from the CustomPopup class in my py file by using 'root.text_1' when the variable is placed outside of the constructor (either before or after), but I cannot do so when placed within. The 'self.title' variable is setup the exact same way as 'self.text_1', but I CAN get that value without issue.
If I un-comment this line, using 'root.text_1' in the kv file returns the correct value.
class CustomPopup( Popup ):
# I can reference this text from the kv file using "root.text_1"
# text_1 = 'blah blah blah'
If instead I try to use 'self.text_1' from within the constructor, I get an Attribute error. However, I have no issues using the variable 'self.title' just below 'self.text_1'.
AttributeError: 'CustomPopup' object has no attribute 'text_1'
def __init__( self, foo = 'bar' ):
super().__init__()
self.foo = foo
# I can't reference this text from the kv file using "root.text_1". Why?
self.text_1 = 'blah blah {foo}'.format( foo = self.foo )
# I can reference this text from the kv file using "root.title"
self.title = 'Title {foo}!'.format( foo = self.foo )
What is the difference here as to why I can get the value from one constructor variable, but not another with ostensibly similar syntax?
I'm using Python 3.7.1 (conda version : 4.5.12) and Kivy 1.10.1.
Python:
import kivy
from kivy import Config
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.popup import Popup
kivy.require( '1.10.1' )
Config.set( 'graphics', 'fullscreen', 0 )
Config.set( 'graphics', 'height', 600 )
Config.set( 'graphics', 'width', 800 )
Config.set( 'graphics', 'resizable', 0 )
Config.set( 'kivy', 'exit_on_escape', 0 )
class CustomPopup( Popup ):
# I can reference this text from the kv file using "root.text_1"
# text_1 = 'blah blah blah'
def __init__( self, foo = 'bar' ):
super().__init__()
self.foo = foo
# I can't reference this text from the kv file using "root.title". Why?
self.text_1 = 'blah blah {foo}'.format( foo = self.foo )
# I can reference this text from the kv file using "root.title"
self.title = 'Title {foo}!'.format( foo = self.foo )
class CustomPopupTestApp( App ):
def build( self ):
return CustomPopup()
#Instantiate top-level/root widget and run it
if __name__ == "__main__":
CustomPopupTestApp().run()
kv:
<CustomPopup>:
id: popup
title: root.title
title_size: 30
title_align: 'center'
size_hint: 0.8, 0.8
auto_dismiss: False
pos_hint: { 'x' : 0.1 , 'y' : 0.1 }
GridLayout:
cols: 1
rows: 2
spacing: 15
padding: 15
Label:
id: content
text: root.text_1
font_size: 25
padding: 15, 25
size_hint_y: None
text_size: self.width, None
height: self.texture_size[ 1 ]
halign: 'center'
GridLayout:
cols: 2
rows: 1
AnchorLayout:
anchor_x : 'center'
anchor_y : 'bottom'
padding: 20
Button:
id: yes
text: 'Yes'
font_size: 30
size_hint: 0.8, 0.4
AnchorLayout:
anchor_x : 'center'
anchor_y : 'bottom'
padding: 20
Button:
id: no
text: 'No'
font_size: 30
size_hint: 0.8, 0.4
I would like to setup the text for my pop-up and use the str.format() method to insert a variable text element so that my message is tailored to the circumstances at hand, rather than generic or hard-coded with multiple options.
In this case, I pass an argument of 'foo' to the constructor, set the variable 'self.foo' equal to 'foo', then refer to 'self.foo' within my 'self.title' string and 'self.text_1' string.
If I place 'text_1' outside of the constructor, while I can retrieve the text value, since 'foo' hasn't been defined within that scope, I can't reference it to format my string.
I am interested in other solutions and any opportunity to learn, but ultimately, if there's a way to make this work without a workaround, that would be ideal.
Thanks in advance for any help. I've already learned a ton from everyone on this site.
P.S. - If I've done something "stupid" or offended your sensibilities, please provide a suggestion or correction rather than just berate me. Sometimes people get negative and it's (usually) not necessary.
答案 0 :(得分:1)
通过研究和测试,我找到了答案。
首先,我没有像以前那样称呼“ self.title”。因此,我没有看到'self.title'与'self.text_1'有不同的行为;我看到了相同的行为。那么,如何才能显示标题而不显示内容?
“弹出”窗口小部件具有“标题”和“内容”的固有属性。当我在CustomPopup()中定义“ self.title”时,我只是提供了该属性的值。即使删除了相应的kv代码“ title:root.title”,仍会显示为“ self.title”定义的相同值。这是关键时刻,因为“ self.title”和“ self.text_1”这两个红色鲱鱼让我分心了。
一旦排除了我在两行本来相同的代码中看到不同行为的问题,我就会更深入地研究如何定义CustomPopup类。那时我碰到了展示如何正确处理该帖子的帖子:Kivy: How to get class Variables in Popup。
长话短说...稍长一点...我更新了我的超级方法以继承我的'text_1'StringProperty,以便可以从CustomPopup对象中引用它!
这是更新的工作解决方案:
Python:
import kivy
from kivy import Config
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.properties import StringProperty
kivy.require( '1.10.1' )
Config.set( 'graphics', 'fullscreen', 0 )
Config.set( 'graphics', 'height', 600 )
Config.set( 'graphics', 'width', 800 )
Config.set( 'graphics', 'resizable', 0 )
Config.set( 'kivy', 'exit_on_escape', 0 )
class CustomPopup( Popup ):
text_1 = StringProperty( '' )
def __init__( self, foo = 'bar' ):
super( CustomPopup, self ).__init__()
self.foo = foo
self.text_1 = 'blah blah {foo}'.format( foo = self.foo )
self.title = 'Title {foo}!'.format( foo = self.foo )
class CustomPopupTestApp( App ):
def build( self ):
blarg = CustomPopup()
return blarg
#Instantiate top-level/root widget and run it
if __name__ == "__main__":
CustomPopupTestApp().run()
kv:
<CustomPopup>:
id: popup
# title: root.title
title_size: 30
title_align: 'center'
size_hint: 0.8, 0.8
auto_dismiss: False
pos_hint: { 'x' : 0.1 , 'y' : 0.1 }
GridLayout:
cols: 1
rows: 2
spacing: 15
padding: 15
Label:
id: content
text: root.text_1
font_size: 25
padding: 15, 25
size_hint_y: None
text_size: self.width, None
height: self.texture_size[ 1 ]
halign: 'center'
GridLayout:
cols: 2
rows: 1
AnchorLayout:
anchor_x : 'center'
anchor_y : 'bottom'
padding: 20
Button:
id: yes
text: 'Yes'
font_size: 30
size_hint: 0.8, 0.4
AnchorLayout:
anchor_x : 'center'
anchor_y : 'bottom'
padding: 20
Button:
id: no
text: 'No'
font_size: 30
size_hint: 0.8, 0.4
请注意,kv文件不再引用“ root.title”,但标题仍可以正确显示。
下面的链接中显示的最终产品是Kivy弹出窗口,其中在kv文件中定义了结构/格式,并在Python中定义了功能和可变文本。对我来说,看起来比在Python方面做的要干净得多。
CustomPopupTest Working Solution
我希望这可以帮助其他人,例如许多其他职位对我有所帮助。