【发布时间】:2020-09-04 20:59:48
【问题描述】:
我是 kivy 的新手。我正在尝试从另一个类更改文本输入值(TextInput 框中显示的字符串值),但没有通过。
我在class MyFirstScreen 中有以下小部件:
- 一个
RecycleView有多个项目(每个项目是一个dictionary) - 两个
TextInputs
我想做的事情:当RecycleView中的每个项目被选中时,TextInputs应该更新并加载所选项目的dictionary的相应值。
但是当我尝试从另一个类 (class SelectableLabel) 访问当前 TextInput 的值时:
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 的框中没有任何反应。
有谁知道我在这里做错了什么或如何使它工作?提前谢谢你...
这是我的 .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)}
【问题讨论】:
-
可能使用
MyFirstScreen()创建类MyFirstScreen的第二个实例,然后从第二个实例读取文本而不是访问原始的第一个实例。当您再次运行update_text_inputs时,您将创建MyFirstScreen类的第三个(第四个、第五个等)实例,而不是使用第一个实例。但只有第一个实例可能有您输入TextInput的文本。