使用纯 Python 在 Kivy 中更改标签

Posted

技术标签:

【中文标题】使用纯 Python 在 Kivy 中更改标签【英文标题】:Changing a label in Kivy using pure Python 【发布时间】:2017-06-29 06:19:13 【问题描述】:

我正在编写一个多子系统项目,其中涉及 3 个 Raspberry Pi 使用套接字通过本地网络相互聊天。在其中一个 Pi 上,我正在编写一个 Kivy 应用程序。我正在尝试在 Kivy 中获取一个标签,以在另一个 Pi 已通过套接字验证它是正常的时更改其文本。

.kv 文件中标签的定义:

Label:
                            id: distance_label
                            markup:True
                            text:"[size=40]Distance:[/size]\n\n[size=60][color=ff0000]NO[/color][/size]"
                            halign:"center"
                            valign:"top"
                            color:black

然后有一个完全独立的 Python 线程,我正在使用它来操作套接字。这会 ping 子系统,然后尝试在成功回复时更改标签:

def test_socket(self, connection):
            Communication.server.send_data(connection,"VERIFY?")
            data_back = Communication.server.receive_data(connection)
            print data_back
            if data_back == "DISTANCE!":
                    # set distance to OK
                    print "Distance is OK"
                    InitScreen().distance_on()

这又会尝试触发 InitScreen 类的 distance_on() 方法。该方法似乎已被触发(如果您将其放入其中,它将打印出一条小的调试消息),但令人讨厌的是标签文本并没有改变其原始值。

class InitScreen(Screen):
    ........

    def distance_on(self, *args):
            distance_label = self.ids['distance_label']
            distance_label.text = "[size=40]Distance:[/size]\n\n[size=60][color=008000]OK[/color][/size]"
            print distance_label.text

在代码的另一部分,我使用 Kivy 中的 on_event 函数通过滑块更改标签的值。这完美地工作。我试图让我的代码看起来与这个工作实例尽可能相似,唯一的区别是我不是试图从 Kivy 事件中触发,而是在 Python 中。

谁能解释一下?是否与调用另一个类的方法有关?身份问题?


这不是一个重复的问题。建议的复制涉及从 Kivy 事件触发函数。我想从 Python 本身触发 Kivy 标签更改——而不是像触摸按钮这样的 Kivy 事件。


这里是所有有问题的代码。我认为这个问题与我使用 ScreenManager 的事实混为一谈,但我不能不这样做!

程序:

class Communication(threading.Thread):
    server = serv.Server()

    def run(self):
            self.setup()
            while distance == False:
                    (connection, address) = self.awaiting_socket()
                    self.test_socket(connection)

    def setup(self):
            Communication.server.setup_server()
            print "SUCCESS ON BIND"

    def awaiting_socket(self):
            print "AWAITING"
            (connection, address) = Communication.server.socket_reception()
            return (connection, address)

    def test_socket(self, connection):
            Communication.server.send_data(connection,"VERIFY?")
            data_back = Communication.server.receive_data(connection)
            print data_back
            if data_back == "DISTANCE!":
                    # set distance to OK
                    print "Distance is OK"
                    application.InitScreen.distance_on()
                    #global distance
                    #distance = True
            if data_back == "STEPPER!":
                    # set stepper to OK
                    print "Stepper is OK"
            ..............

class InitScreen(Screen):
    def power_off(self, *args):
            onoffswitch = self.ids["onoffswitch"]
            onoff_value = onoffswitch.active
            if onoff_value == False:
                    subprocess.call(powerdown)

    def distance_on(self):
            distance_label = self.ids["distance_label"]
            distance_label.text = "[size=40]Distance:[/size]\n\n[size=60][color=008000]OK[/color][/size]"

class ScreenManagement(ScreenManager):
    pass

application = Builder.load_file("main.kv")

class LidarApp(App):
           def build(self):
                return application

KIVY 定义屏幕管理器:

ScreenManagement:
    transition: FadeTransition()
    InitScreen:
    MainScreen:

KIVY 在问题中定义标签:

Label:
                            id: distance_label
                            markup:True
                            text:"[size=40]Distance:[/size]\n\n[size=60][color=ff0000]NO[/color][/size]"
                            on_text:
                            halign:"center"
                            valign:"top"
                            color:black

【问题讨论】:

How to change text of a label in the kivy language with python的可能重复 将标签设置为 StringProperty(),然后将标签的文本设置为此变量。然后会更新。label = StringProperty() \n distance_variable.text = label 此线程与上述线程并不完全重复。我对 StringProperty()s 很陌生?您介意解释一下在我的情况下如何使用它吗? ` InitScreen().distance_on()` 创建了一个 InitScreen 的 new 实例,但从不做任何事情,而听起来你有一个现有的 InitScreen,你的行为想要改变。您需要获取对此现有 InitScreen 的引用并调用该实例的 distance_on 方法。 啊当然。我知道这是我的 Python 错误。对类、线程等仍然相当新。您建议如何获取对现有 InitScreen 的引用? 【参考方案1】:

正如test_socket 中的 cmets 中所讨论的,您需要获取当前屏幕。为此,您需要使用ScreenManager.current_screen

Builder.load_file 返回一个 ScreenManager。这意味着您需要使用您的 application 全局变量。

您完成的代码:

def test_socket(self, connection):
    Communication.server.send_data(connection,"VERIFY?")
    data_back = Communication.server.receive_data(connection)
    print data_back
    if data_back == "DISTANCE!":
            # set distance to OK
            print "Distance is OK"
            application.current_screen.distance_on()

【讨论】:

以上是关于使用纯 Python 在 Kivy 中更改标签的主要内容,如果未能解决你的问题,请参考以下文章

Python Kivy - 更改标签颜色

如何从 python 文件中更改 kivy 标签的文本?

Python Kivy - 下划线在标签中不起作用

我正在尝试使用 python 文件在 kivy 中添加标签。但它每次都抛出错误

Kivy,从python文件更改画布的源图片

Python:如何在 kivy 中使标签加粗