Kivy - 让按钮改变 TextInput 的文本?

Kivy - Make buttons change the text of TextInput?

我正在尝试制作一个带有 3 个按钮和一个显示器的应用程序(我正在使用 TextInput)。

按下按钮时,我希望按钮的文本显示在显示屏上。例如,如果您按 1 1 2,我希望显示屏上显示 112。

有没有办法不用手动向每个按钮添加 on_press 就可以做到这一点?这是不起作用的代码。我认为它不起作用,因为 "self.ids.textbox.text" 指的是错误的东西。我不确定如何更正此问题。

不工作main2.py:

import kivy
kivy.require("1.9.0")

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window

class Buttons(Button):

    def callback(self, text):
        self.ids.textbox.text = "Hi"


class Main2Widget(BoxLayout):

    pass

class Main2App(App):
    '''docstring for Main2App'''
    def build(self):
        Window.size = (300, 200)
        return Main2Widget()


if __name__ == "__main__":
    Main2App().run()

不工作main2.kv:

#:kivy 1.9.0

<Buttons>:
    on_press: root.callback(self.text)

<Main2Widget>:
    id: mainapp

    orientation: 'vertical'

    TextInput:
        id: textbox
        multiline: False
        readonly: True

        hint_text: "I'm an input box!"
        font_size: 20

    GridLayout:
        cols: 3

        Buttons:
            id: btn1
            text: "1"

        Buttons:
            id: btn2
            text: "2"

        Buttons:
            id: btn3
            text: "3"

如果我这样做,它会起作用:

工作main2.py:

import kivy
kivy.require("1.9.0")

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window


class Main2Widget(BoxLayout):

    def callback(self, text):
        self.ids.textbox.text += text

    pass

class Main2App(App):
    '''docstring for Main2App'''
    def build(self):
        Window.size = (300, 200)
        return Main2Widget()


if __name__ == "__main__":
    Main2App().run()

工作main2.kv:

#:kivy 1.9.0

<Main2Widget>:
    orientation: 'vertical'

    TextInput:
        id: textbox
        multiline: False
        readonly: True

        hint_text: "I'm an input box!"
        font_size: 20

    GridLayout:
        cols: 3

        Button:
            id: btn1
            text: "1"
            on_press: root.callback(self.text)

        Button:
            id: btn2
            text: "2"
            on_press: root.callback(self.text)

        Button:
            id: btn3
            text: "3"
            on_press: root.callback(self.text)

它不起作用的原因是因为 root 指的是当前规则的根(在本例中为 <Buttons>)。规则的根还包含该规则中包含的 ID,因此函数在 Buttons 上调用,但由于它没有 ID,因此 self.ids 为空。

在您的第二个示例中,root 引用 <Main2Widget>,它在其规则中确实包含一个 ID 为 textbox 的小部件。

一般来说,小部件规则 (<Buttons>) 无法访问其自身规则之外的小部件。这是因为它可以插入任何地方,可能有也可能没有任何东西可以访问。

App 对象除外。您可以在 kv 中的任何地方访问您的应用程序对象。

我可以想到 3 种解决方法来解决您的问题。最简单的方法是将函数调用放在 <Main2Widget> 规则(您试过)中。如果你真的想要一个单独的按钮规则,那么第二个选项是将 callback 函数放在你的 App class 中,然后调用 app.callback。然后你可以只保留对你的根小部件的引用:

class Main2App(App):
    '''docstring for Main2App'''    
    def build(self):
        Window.size = (300, 200)
        self.root =  Main2Widget()
        return self.root

    def callback(self, text):
        self.root.ids.textbox.text = "Hi"

最后一个,也是我可能会使用的一个,是利用 StringProperty(也在 App class 上):

class Main2App(App):
    '''docstring for Main2App'''
    the_text = StringProperty()
    def build(self):
        Window.size = (300, 200)
        return Main2Widget()

然后你可以用text: app.the_text将textinput绑定到属性,然后用on_press: app.the_text = self.text在按钮中设置它。我认为这更干净,因为您不需要使用回调或访问 python 端的 ID。