【问题标题】:Label not updating Kivy标签未更新 Kivy
【发布时间】:2018-05-22 07:35:23
【问题描述】:

所以我有两个文件:

  1. returnStation.py
  2. returnStationLayout.kv

我想要实现的目标:有两个屏幕。一种是数字键盘。输入号码并按 Enter 后,它会将您带到下一个屏幕。我希望另一个屏幕显示你刚刚键入的数字。

我面临的问题:我尝试访问我尝试更改的标签的 ID 以显示数字,但它不起作用:/我在终端中没有收到任何错误。

我会以错误的方式访问这些值吗?如果是这样,请告知如何最好地在两个屏幕中进行。感谢任何帮助!


这是文件 - returnStation.py:

我尝试更改标签的方法是通过 getPoints()

import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout

class ScreenOne(Screen):
    pass

class ScreenTwo(Screen):
    pass

class PhoneGridLayout(GridLayout):

    def backspace(self, textString):
        newTextString = textString[0:-1]
        self.display.text = newTextString

    def getPoints(self, phoneNumber):
        st = ScreenTwo()
        st.ids.memberStatus.text = phoneNumber   #THIS IS HOW I ATTEMPTED TO CHANGE THE LABEL

class ReturnStationLayoutApp(App):
    pass


mainscreen = ScreenOne()
mainlayout = PhoneGridLayout()
mainscreen.add_widget(mainlayout)

if __name__ == '__main__':
    ReturnStationLayoutApp().run()

这是文件 - returnStationLayout.kv:

我要更改的标签一直在这个文件的底部

ScreenManager:
    id: screen_manager
    ScreenOne:
        id: screen_one
        name: 'menu'
        manager: 'screen_manager'
    ScreenTwo:
        id: screen_two
        name: 'settings'
        manager: 'screen_manager'

<CustButton@Button>:
    font_size: 32

<ScreenOne>:
    PhoneGridLayout:
        id: numberPad
        display: entry
        rows: 5
        padding: [300,200]
        spacing: 10

        # Where input is displayed
        BoxLayout:
            Label:
                text: "+65"
                font_size: 50
                size_hint: 0.2, 1
            TextInput:
                id: entry
                font_size: 50
                multiline: False
                padding: [20, ( self.height - self.line_height ) / 2]


        BoxLayout:
            spacing: 10
            CustButton:
                text: "1"
                on_press: entry.text += self.text
            CustButton:
                text: "2"
                on_press: entry.text += self.text
            CustButton:
                text: "3"
                on_press: entry.text += self.text
            CustButton:
                text: "DEL"
                on_press: numberPad.backspace(entry.text)

        BoxLayout:
            spacing: 10
            CustButton:
                text: "4"
                on_press: entry.text += self.text
            CustButton:
                text: "5"
                on_press: entry.text += self.text
            CustButton:
                text: "6"
                on_press: entry.text += self.text
            CustButton:
                text: "AC"
                on_press: entry.text = ""

        BoxLayout:
            spacing: 10
            CustButton:
                text: "7"
                on_press: entry.text += self.text
            CustButton:
                text: "8"
                on_press: entry.text += self.text
            CustButton:
                text: "9"
                on_press: entry.text += self.text
            CustButton:
                text: "Enter" #HERE IS THE ENTER BUTTON
                on_press:
                    app.root.transition.direction = 'left'
                    app.root.transition.duration = 1
                    app.root.current = 'settings'
                    numberPad.getPoints(entry.text)

        BoxLayout:
            spacing: 10
            Label:
                text: ""
            CustButton:
                text: "0"
                on_press: entry.text += self.text
            Label:
                text: ""
            Label:
                text: ""

<ScreenTwo>:
    BoxLayout:
        Label:
            id: memberStatus
            text: ''  #THIS IS THE LABEL I AM TRYING TO CHANGE
        Button:
            text: 'Back to menu'
            on_press:
                app.root.transition.direction = "right"
                app.root.current = 'menu'

【问题讨论】:

    标签: python python-2.7 kivy


    【解决方案1】:

    您可以应用的最小修复是将getPoints 方法移动到您的ReturnStationLayoutApp 类,并从那里更新所需的字段,就像这样:

    class ReturnStationLayoutApp(App):
    
        def getPoints(self, phoneNumber):
            self.root.ids.screen_two.ids.memberStatus.text = phoneNumber
    

    当然,这需要将 .kv 文件中的 numberPad.getPoints(entry.text) 行更改为 app.getPoints(entry.text)

    【讨论】:

    • 你的也很完美!但是,我发现 ikolim 的方式更像是一种“最佳实践”。感谢您的回复!
    • @KwkWenJian Ikolim 的方式当然更好,但需要更多的代码更改,如果您有时间应用它们,您绝对应该这样做。如果您的应用程序变得更大,我还建议将每个 .kv 屏幕布局分开。
    • 这是一个值得记住的好建议。您能否帮助我解决我面临的其他问题:stackoverflow.com/questions/50483687/…
    【解决方案2】:

    使用 Kivy ObjectPropertyScreenManager,可以在 kv 文件中使用 root.manager...self.manager 在 Python 脚本中。

    详情请参考以下建议和示例。

    1. 为 ScreenManager 定义一个类,并为 ScreenOne 和 ScreenTwo 声明 ObjectProperty。
    2. 使用 ScreenManager,将 kv 文件中的 app.root... 替换为 root.manager...
    3. 在ScreenOne类中实现PhoneGridLayout类中的两个方法,并删除类PhoneGridLayout
    4. 为 ScreenTwo 类中的 memberStatus 声明一个 ObjectProperty。
    5. 删除 st = ScreenTwo(),因为不想实例化 ScreenTwo 的另一个对象,该对象与 kv 文件中已实例化的对象不同。
    6. st.ids.memberStatus.text 替换为 self.manager.screen_two.member_status.text

    Screen Manager » Basic Usage

    创建两个屏幕。请注意 root.manager.current:这是如何 您可以从 kv 控制 ScreenManager。每个屏幕默认有一个 为您提供所用 ScreenManager 实例的属性管理器。

    Programming Guide » Kv language

    虽然 self.ids 方法非常简洁,但通常认为使用 ObjectProperty 是“最佳实践”。这会创建一个直接引用,提供更快的访问速度并且更明确。

    示例

    returnStation.py

    ​​>
    from kivy.app import App
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.properties import ObjectProperty
    
    
    class ScreenManagement(ScreenManager):
        screen_one = ObjectProperty(None)
        screen_two = ObjectProperty(None)
    
    
    class ScreenOne(Screen):
        member_status = ObjectProperty(None)
    
        def backspace(self, textString):
            newTextString = textString[0:-1]
            self.display.text = newTextString
    
        def getPoints(self, phoneNumber):
            print(phoneNumber)
            self.manager.screen_two.member_status.text = phoneNumber   #THIS IS HOW I ATTEMPTED TO CHANGE THE LABEL
    
    
    class ScreenTwo(Screen):
        pass
    
    
    class ReturnStationLayoutApp(App):
    
        def build(self):
            return ScreenManagement()
    
    
    if __name__ == '__main__':
        ReturnStationLayoutApp().run()
    

    returnstationlayout.kv

    #:kivy 1.10.0
    
    <ScreenManagement>:
        screen_one: screen_one
        screen_two: screen_two
    
        ScreenOne:
            id: screen_one
            name: 'menu'
        ScreenTwo:
            id: screen_two
            name: 'settings'
    
    <CustButton@Button>:
        font_size: 32
    
    <ScreenOne>:
        display: entry
        # PhoneGridLayout
        GridLayout:
            id: numberPad
            rows: 5
            padding: [300,200]
            spacing: 10
    
            # Where input is displayed
            BoxLayout:
                Label:
                    text: "+65"
                    font_size: 50
                    size_hint: 0.2, 1
                TextInput:
                    id: entry
                    font_size: 50
                    multiline: False
                    padding: [20, ( self.height - self.line_height ) / 2]
    
    
            BoxLayout:
                spacing: 10
                CustButton:
                    text: "1"
                    on_press: entry.text += self.text
                CustButton:
                    text: "2"
                    on_press: entry.text += self.text
                CustButton:
                    text: "3"
                    on_press: entry.text += self.text
                CustButton:
                    text: "DEL"
                    on_press: root.backspace(entry.text)
    
            BoxLayout:
                spacing: 10
                CustButton:
                    text: "4"
                    on_press: entry.text += self.text
                CustButton:
                    text: "5"
                    on_press: entry.text += self.text
                CustButton:
                    text: "6"
                    on_press: entry.text += self.text
                CustButton:
                    text: "AC"
                    on_press: entry.text = ""
    
            BoxLayout:
                spacing: 10
                CustButton:
                    text: "7"
                    on_press: entry.text += self.text
                CustButton:
                    text: "8"
                    on_press: entry.text += self.text
                CustButton:
                    text: "9"
                    on_press: entry.text += self.text
                CustButton:
                    text: "Enter" #HERE IS THE ENTER BUTTON
                    on_press:
                        root.manager.transition.direction = 'left'
                        root.manager.transition.duration = 1
                        root.manager.current = 'settings'
                        root.getPoints(entry.text)
    
            BoxLayout:
                spacing: 10
                Label:
                    text: ""
                CustButton:
                    text: "0"
                    on_press: entry.text += self.text
                Label:
                    text: ""
                Label:
                    text: ""
    
    <ScreenTwo>:
        member_status: memberStatus
        BoxLayout:
            Label:
                id: memberStatus
                text: ''  #THIS IS THE LABEL I AM TRYING TO CHANGE
            Button:
                text: 'Back to menu'
                on_press:
                    root.manager.transition.direction = "right"
                    root.manager.current = 'menu'
    

    输出

    【讨论】:

    • 嗨,@ikolim!感谢您的详细回答!您能否向我解释一下 self.manager 中的“经理”是否指的是“ScreenOne:id:screen_one name:'menu' manager:screen_manager”中的那个?如果是,这部分的作用是什么?我的原始代码中确实有它,但我不太了解它的功能。
    • @KwokWenJian:默认情况下,每个屏幕都有一个属性 manager,它为您提供所使用的 ScreenManager 的实例。我更新了我的帖子,提供了 Kivy ScreenManager 文档的链接,并删除了混淆代码、id: screen_managermanager: screen_manager
    • 感谢您的更新和删除令人困惑的代码。还有一个问题:为什么 member_status = ObjectProperty(None) 在 ScreenOne 下被声明在 ScreenTwo 下?您的代码有效,但我很困惑,我无法从您包含的链接中得到答案:/
    • 而且不需要“从 kivy.uix.gridlayout 导入 GridLayout”?这是怎么回事?
    • 从 Python 脚本中删除了 GridLayout 的导入语句,因为我们已经删除了 phoneGridLayout 类并将这两个方法移到了 ScreenTwo 类中。在 kv 文件中,我们将 phoneGridLayout 替换为 GridLayout。抱歉打错字了,我已将 ObjectProperty member_status 移到 ScreenTwo 类中。
    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    相关资源
    最近更新 更多