Kivy:无法更新其他类的文本输入值 [英] Kivy: Can't update text input value from another class

查看:63
本文介绍了Kivy:无法更新其他类的文本输入值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是kivy的新手.我正在尝试从另一个类更改文本输入值(TextInput框中显示的字符串值),但没有任何反应.

I'm new on kivy.I'm trying to change text input value (the string value that is shown in TextInput box) from another class, But nothing passes.

我在class MyFirstScreen中有以下小部件:

  • 一个RecycleView具有多个项目(每个项目是一个dictionary)
  • 两个TextInput s
  • One RecycleView with multiple items (each item is a dictionary)
  • Two TextInputs

我想要做的:每个项目中选择,取值应该是更新和负载相应的选择项的值是<4>

What I want to do: When each items in RecycleView selected, TextInputs should be update and load with corresponding values of selected item's dictionary.

但是当我尝试从另一个类(class SelectableLabel)访问当前TextInput的值时:

But when i try to access current TextInput's value from another class (class SelectableLabel):

class SelectableLabel(RecycleDataViewBehavior, Label):
    #...
    def update_text_inputs(self, *kwarg):
        my_text_input = MyFirstScreen().ids.system_name_text_input_id #<--i can access to widget
        print("my_print_val is:", my_text_input.text) #<--but widget's current text value is : ''
        my_text_input.text = "Updated Value"

我可以访问my_text_input小部件,但其文本(my_text_input.text)是一个空字符串('').此外,当我更改my_text_input.text的值时,TextInput的框中没有任何反应.

I can access to my_text_input widget but its text (my_text_input.text) is an empty string ('').Furthermore when i change the value of my_text_input.text, nothing happens in TextInput's box.

有人知道我在这里做错什么或如何做这项工作吗?预先谢谢你...

Does anyone know what am I doing wrong here or how to make this work? Thank you in advance...

这是我的.py代码:

from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior


class Manager(ScreenManager):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class MyFirstScreen(Screen):
    system_name_text_input_id = ObjectProperty(None)

    def __init__(self, **kwarg):
        super().__init__(**kwarg)
        print("__init__ of MyFirstScreen is Called")

    def get_text_inputs(self):
        ret_val = self.ids.system_name_text_input_id.text
        print("get_text_input is called, ret_val:", ret_val)
        return ret_val


class RecycleViewWidget(RecycleView):
    def __init__(self, **kwargs):
        super(RecycleViewWidget, self).__init__(**kwargs)
        self.items_of_rv = []
        for i in range(1, 21):
            self.items_of_rv.append(
                {"color": (0, 0, 0, 1), "font_size": "20", "text": f"User {i}",
                 "user_id": f"{100 * i}"})
        self.data = [item for item in self.items_of_rv]


class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
    """ Adds selection and focus behaviour to the view. """


class SelectableLabel(RecycleDataViewBehavior, Label):
    """ Add selection support to the Label """
    index = None
    selected = BooleanProperty(False)
    selectable = BooleanProperty(True)

    def refresh_view_attrs(self, rv, index, data):
        """ Catch and handle the view changes """
        self.index = index
        return super(SelectableLabel, self).refresh_view_attrs(rv, index, data)

    def on_touch_down(self, touch):
        """ Add selection on touch down """
        if super(SelectableLabel, self).on_touch_down(touch):
            return True
        if self.collide_point(*touch.pos) and self.selectable:
            return self.parent.select_with_touch(self.index, touch)

    def apply_selection(self, rv, index, is_selected):
        """ Respond to the selection of items in the view. """

        self.selected = not is_selected
        if is_selected:
            rv.data[index].update({'color': (1, 1, 1, 1)})
            self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
            print("selection changed to {0}".format(rv.data[index]))
            self.update_text_inputs()
        else:
            if rv.data[index].get("color") == (1, 1, 1, 1):
                rv.data[index].update({'color': (0, 0, 0, 1)})
                self.refresh_view_attrs(RecycleViewWidget(), index, rv.data[index])
        self.selected = not self.selected

    def update_text_inputs(self, *kwarg):
        my_text_input = MyFirstScreen().ids.system_name_text_input_id#<--i can access to widget
        print("my_print_val is:", my_text_input.text)#<--but widget's current text value is : ''
        # my_text_input.text = "Updated Value" 

main_style = Builder.load_file("test.kv")


class MyApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def build(self):
        return main_style


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

以及我的.kv代码:

Manager:
    MyFirstScreen:

<SelectableLabel>:
    canvas.before:
        Color:
            rgba: (0, 0, 1, 1) if self.selected else (1, 1, 1, 1)
        Rectangle:
            pos: self.pos
            size: self.size
<RecycleViewWidget>:
    viewclass: 'SelectableLabel'
    SelectableRecycleBoxLayout:
        default_size: None, dp(56)
        default_size_hint: 1, None
        size_hint_y: None
        height: self.minimum_height
        orientation: 'vertical'

<MyFirstScreen>:
    name: 'system_setup_page'
    system_name_text_input_id:system_name_text_input_id
    GridLayout:
        cols: 2
        BoxLayout:
            cols: 1
            padding: 20
            RecycleViewWidget:
        FloatLayout:
            Label:
                size_hint: None, None
                text: "Name:"
                font_size: 22
                pos_hint: {'center': (20/100, 90/100)}
            TextInput:
                id: system_name_text_input_id
                size_hint: None, None
                hint_text: "Type Your Name..."
                size: 200, 30
                multiline: False
                pos_hint: {'center': (65/100, 90/100)}
                on_text: root.get_text_inputs()
            Label:
                size_hint: None, None
                text: "User ID:"
                font_size: 20
                pos_hint: {'center': (20/100, 70/100)}
            TextInput:
                size_hint: None, None
                size: 200, 30
                hint_text: "Type Your ID..."
                pos_hint: {'center': (65/100, 70/100)}

推荐答案

问题是因为在update_text_inputs()中使用MyFirstScreen()可以创建类MyFirstScreen的新实例,但是必须使用现有实例.

Problem is because using MyFirstScreen() in update_text_inputs() you create new instance of class MyFirstScreen but you have to use existing instance.

应该是更好的方法,但是目前我唯一的想法是为此使用parent.

It should be better way to get it but at this moment my only idea is to use parent for this .

因为这些元素之间有许多小部件,所以它需要许多parent:

Because there are many widgets between these elements so it needs many parent:

    my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id  

我使用print(self.parent),下一个print(self.parent.parent)等找到了它.

I found it using print(self.parent), next print(self.parent.parent), etc.

def update_text_inputs(self, *kwarg):
    #print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id)
    #print('parent:', self.parent.parent.parent.parent.parent.system_name_text_input_id.text)

    my_text_input = self.parent.parent.parent.parent.parent.system_name_text_input_id 

    print("my_print_val is:", my_text_input.text)

    my_text_input.text = "Updated Value" 

这篇关于Kivy:无法更新其他类的文本输入值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆