首页 > 解决方案 > 为什么我不能从我的 kv 文件的构造函数中引用 self.text_1 ?

问题描述

我正在研究一个简单的 Kivy Popup,我很困惑为什么我不能从 Popup 类的构造函数中引用我的类变量“self.text_1”,但我可以使用变量'自.title'。

首先,我将从无处不在的“我是 Python 和 Kivy 的新手,所以也许我只是遗漏了一些明显的东西,但我不知所措”开始。

我试图找到答案,但到目前为止似乎没有任何内容涵盖这个主题,至少在某种程度上我可以理解和绘制连接。下面是我的问题和一些简化的演示代码。

在 kv 文件 > 标签小部件 > 文本中,当变量放置在构造函数之外(之前或之后)时,我可以使用“root.text_1”从我的 py 文件中的 CustomPopup 类中引用“text_1”,但是放在里面时我不能这样做。“self.title”变量的设置方式与“self.text_1”完全相同,但我可以毫无问题地获得该值。

如果我取消注释这一行,在 kv 文件中使用“root.text_1”会返回正确的值。

class CustomPopup( Popup ):
    # I can reference this text from the kv file using "root.text_1"
    # text_1 = 'blah blah blah'

相反,如果我尝试在构造函数中使用“self.text_1”,则会收到属性错误。但是,使用“self.text_1”下方的变量“self.title”没有问题。

AttributeError:“CustomPopup”对象没有属性“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 )

为什么我可以从一个构造函数变量中获取值,但不能从表面上相似的语法中获取另一个值,这里有什么区别?

我正在使用 Python 3.7.1(conda 版本:4.5.12)和 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()

千伏:

<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

我想为我的弹出窗口设置文本并使用 str.format() 方法插入可变文本元素,以便我的消息适合手头的情况,而不是通用或硬编码的多个选项。

在这种情况下,我将“foo”的参数传递给构造函数,将变量“self.foo”设置为“foo”,然后在“self.title”字符串和“self.foo”中引用“self.foo”。 text_1' 字符串。

如果我将 'text_1' 放在构造函数之外,虽然我可以检索文本值,但由于尚未在该范围内定义 'foo',我无法引用它来格式化我的字符串。

我对其他解决方案和任何学习机会感兴趣,但最终,如果有一种方法可以在没有解决方法的情况下完成这项工作,那将是理想的。

提前感谢您的帮助。我已经从这个网站上的每个人那里学到了很多东西。

PS - 如果我做了一些“愚蠢”的事情或冒犯了你的感情,请提供建议或更正,而不是仅仅责备我。有时人们会变得消极,这(通常)是没有必要的。

标签: pythonpython-3.xkivykivy-language

解决方案


通过研究和测试,我找到了答案。

事实证明,首先,我并没有像我想象的那样称呼“self.title”。因此,我没有看到“self.title”与“self.text_1”的不同行为;我看到了同样的行为。那么,我如何才能显示我的标题,而不是我的内容?

Popup 小部件具有“标题”和“内容”的固有属性。当我在 CustomPopup() 中定义“self.title”时,我只是提供了该属性的值。即使删除了相应的 kv 代码 'title: root.title',仍然会显示为 'self.title' 定义的相同值。这是关键时刻,我被“self.title”与“self.text_1”的红鲱鱼分心了。

一旦我排除了我看到两行相同代码行的不同行为的问题,我就更深入地研究了我是如何定义我的 CustomPopup 类的。就在那时,我看到了这篇文章,它展示了如何正确处理这个问题:Kivy:如何在 Popup 中获取类变量

长话短说……稍长……我更新了我的超级方法以继承我的“text_1”字符串属性,以便我可以从 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()

千伏:

<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 工作解决方案

我希望这对其他人有所帮助,就像许多其他帖子对我有所帮助一样。


推荐阅读