如何 enable/disable 在 python 中将多个 TextInput 集中在 kivy 中
how to enable/disable multiple TextInput on focusing in kivy in python
我正在尝试 enable/disable 在 kivy 中输入文本。那里有多个 TextInput。 (1) 当我点击一个 TextInput 时,那个特定的 TextInput 将是可编辑的。 (2) 默认情况下,所有内容都将设置为禁用模式。 (3) 滚动条应该在那里,因为假设那里有数百个输入。(我无法带那个)。 (4) 我面临的另一个问题是:当有数百个输入时,TextInput 的文本无法正确显示。那么是否有任何选项可以设置默认大小,这样它就不会影响只有 2-3 个输入还是 100 个输入。 (5) TextInput 和label 的值应该是动态的,应该存储在全局变量中。 @PalimPalim 已经为我提供了现有代码。谢谢大家。
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
ROWS = ['ac', 'asd', 'kjhgf', 'b' ,'bn', 'sdf', 'ytrwd', 'hfs' ,'erf', ...]
Builder.load_string("""
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
scrollView:
size_hint: (None, None)
size: (400, 400)
Table:
padding: 50, 50, 50, 50
orientation: 'vertical'
<Row>:
spacing: 50
size_hint: 1, .9
txt: txtinpt.text
Label:
text: root.txt
TextInput:
id: txtinpt
text: root.txt
Button:
text: 'save'
""")
class Table(BoxLayout):
def __init__(self, **kwargs):
super(Table, self).__init__(**kwargs)
for row in ROWS:
self.add_widget(Row(row))
class Row(BoxLayout):
txt = StringProperty()
def __init__(self, row, **kwargs):
super(Row, self).__init__(**kwargs)
self.txt = row
class ScrollableLabel(ScrollView):
text = StringProperty('')
class Test(TabbedPanel):
pass
class MyApp(App):
def build(self):
test = Test()
return test
if __name__ == '__main__':
MyApp().run()
好的,首先,你想让行数动态变化,而且可能很大,所以你不想自己创建和管理所有行,这在填充时和滚动时都非常慢,你想使用 RecyclevView。
RecycleView 接受一个字典列表,其中包含您的小部件的数据,以及一个 class 来显示它们,将根据需要创建尽可能多的字典以填充滚动视图的可见部分(它管理), 并在滚动时将正确的数据提供给正确的行,定位它们以产生无限流的错觉,这使您可以毫不费力地管理数百 的 行,而您的目前的方式一般在几百条后就不能用了。
用法很简单,你已经有了一个项目列表,但是里面只有文本,让我们把它转换成一个字典列表,然后把它放在应用程序中,以便于从 kv 中引用。
class MyApp(App):
data = ListProperty()
def build(self):
self.data = [{'row_id': i, 'text': x} for i, x in enumerate(ROWS)]
test = Test()
return test
现在,让我们用 RecycleView 替换您的 ScrollView
#:import Factory kivy.factory.Factory
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
RecycleView:
size_hint: (None, None)
size: (400, 400)
data: app.data
viewclass: Factory.Row
RecycleBoxLayout:
padding: 50, 50, 50, 50
size_hint_y: None
size: self.minimum_size
default_size_hint: 1, None
default_size: 0, dp(36) # width is overriden by size_hint_x
orientation: 'vertical'
我们自动调整大小,这里 RecycleView 占用所有可用的 space(您可以调整 window 的大小以给它 less/more space),以及 RecycleBoxLayout inside 和它需要的一样大,从它的行的大小计算,这是静态定义的,以避免你的(4)中描述的效果。因此滚动条在需要时出现,即当 RecycleBoxLayout 大于 RecycleView 时。
现在,修复行 class 以便在回收视图中使用适当的大小和用法。
<Row>:
spacing: 50
text: txtinpt.text
Label:
text: root.text
TextInput:
id: txtinpt
text: root.text
Button:
text: 'save'
on_press:
app.data[root.row_id]['text'] = root.text
和
class Row(BoxLayout):
text = StringProperty()
row_id = NumericProperty()
这里的想法是保存将编辑应用程序中的源数据,使用行 ID 知道将它放在哪里,非常简单。
现在,我并没有真正了解禁用文本输入,您是说 focused/unfocused 吗?因为如果禁用 textinputs,触摸它们不会给它们焦点,因此 (1) 将无法实现,如果禁用 textinputs,则需要为用户提供启用它们的方法。
完整节目
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty, NumericProperty
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
ROWS = ['ac', 'asd', 'kjhgf', 'b', 'bn', 'sdf', 'ytrwd', 'hfs', 'erf', 'boo']
# now make a lot more of them, to see performances, yep, 100k items...
ROWS = ROWS * 10000
Builder.load_string("""
#:import Factory kivy.factory.Factory
#:import dp kivy.metrics.dp
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
RecycleView:
# size_hint: (None, None)
# size: (400, 400)
data: app.data
viewclass: Factory.Row
RecycleBoxLayout:
padding: 50, 50, 50, 50
orientation: 'vertical'
size_hint: 1, None
size: self.minimum_size
default_size_hint: 1, None
default_size: 0, dp(36)
<Row>:
spacing: 50
text: txtinpt.text
Label:
text: root.text
TextInput:
id: txtinpt
text: root.text
Button:
text: 'save'
on_press:
app.data[root.row_id]['text'] = root.text
""")
class Row(BoxLayout):
text = StringProperty()
row_id = NumericProperty()
class Test(TabbedPanel):
pass
class MyApp(App):
data = ListProperty()
def build(self):
self.data = [{'row_id': i, 'text': x} for i, x in enumerate(ROWS)]
test = Test()
return test
if __name__ == '__main__':
MyApp().run()
我正在尝试 enable/disable 在 kivy 中输入文本。那里有多个 TextInput。 (1) 当我点击一个 TextInput 时,那个特定的 TextInput 将是可编辑的。 (2) 默认情况下,所有内容都将设置为禁用模式。 (3) 滚动条应该在那里,因为假设那里有数百个输入。(我无法带那个)。 (4) 我面临的另一个问题是:当有数百个输入时,TextInput 的文本无法正确显示。那么是否有任何选项可以设置默认大小,这样它就不会影响只有 2-3 个输入还是 100 个输入。 (5) TextInput 和label 的值应该是动态的,应该存储在全局变量中。 @PalimPalim 已经为我提供了现有代码。谢谢大家。
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty
ROWS = ['ac', 'asd', 'kjhgf', 'b' ,'bn', 'sdf', 'ytrwd', 'hfs' ,'erf', ...]
Builder.load_string("""
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
scrollView:
size_hint: (None, None)
size: (400, 400)
Table:
padding: 50, 50, 50, 50
orientation: 'vertical'
<Row>:
spacing: 50
size_hint: 1, .9
txt: txtinpt.text
Label:
text: root.txt
TextInput:
id: txtinpt
text: root.txt
Button:
text: 'save'
""")
class Table(BoxLayout):
def __init__(self, **kwargs):
super(Table, self).__init__(**kwargs)
for row in ROWS:
self.add_widget(Row(row))
class Row(BoxLayout):
txt = StringProperty()
def __init__(self, row, **kwargs):
super(Row, self).__init__(**kwargs)
self.txt = row
class ScrollableLabel(ScrollView):
text = StringProperty('')
class Test(TabbedPanel):
pass
class MyApp(App):
def build(self):
test = Test()
return test
if __name__ == '__main__':
MyApp().run()
好的,首先,你想让行数动态变化,而且可能很大,所以你不想自己创建和管理所有行,这在填充时和滚动时都非常慢,你想使用 RecyclevView。
RecycleView 接受一个字典列表,其中包含您的小部件的数据,以及一个 class 来显示它们,将根据需要创建尽可能多的字典以填充滚动视图的可见部分(它管理), 并在滚动时将正确的数据提供给正确的行,定位它们以产生无限流的错觉,这使您可以毫不费力地管理数百 的 行,而您的目前的方式一般在几百条后就不能用了。
用法很简单,你已经有了一个项目列表,但是里面只有文本,让我们把它转换成一个字典列表,然后把它放在应用程序中,以便于从 kv 中引用。
class MyApp(App):
data = ListProperty()
def build(self):
self.data = [{'row_id': i, 'text': x} for i, x in enumerate(ROWS)]
test = Test()
return test
现在,让我们用 RecycleView 替换您的 ScrollView
#:import Factory kivy.factory.Factory
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
RecycleView:
size_hint: (None, None)
size: (400, 400)
data: app.data
viewclass: Factory.Row
RecycleBoxLayout:
padding: 50, 50, 50, 50
size_hint_y: None
size: self.minimum_size
default_size_hint: 1, None
default_size: 0, dp(36) # width is overriden by size_hint_x
orientation: 'vertical'
我们自动调整大小,这里 RecycleView 占用所有可用的 space(您可以调整 window 的大小以给它 less/more space),以及 RecycleBoxLayout inside 和它需要的一样大,从它的行的大小计算,这是静态定义的,以避免你的(4)中描述的效果。因此滚动条在需要时出现,即当 RecycleBoxLayout 大于 RecycleView 时。
现在,修复行 class 以便在回收视图中使用适当的大小和用法。
<Row>:
spacing: 50
text: txtinpt.text
Label:
text: root.text
TextInput:
id: txtinpt
text: root.text
Button:
text: 'save'
on_press:
app.data[root.row_id]['text'] = root.text
和
class Row(BoxLayout):
text = StringProperty()
row_id = NumericProperty()
这里的想法是保存将编辑应用程序中的源数据,使用行 ID 知道将它放在哪里,非常简单。
现在,我并没有真正了解禁用文本输入,您是说 focused/unfocused 吗?因为如果禁用 textinputs,触摸它们不会给它们焦点,因此 (1) 将无法实现,如果禁用 textinputs,则需要为用户提供启用它们的方法。
完整节目
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty, NumericProperty
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
ROWS = ['ac', 'asd', 'kjhgf', 'b', 'bn', 'sdf', 'ytrwd', 'hfs', 'erf', 'boo']
# now make a lot more of them, to see performances, yep, 100k items...
ROWS = ROWS * 10000
Builder.load_string("""
#:import Factory kivy.factory.Factory
#:import dp kivy.metrics.dp
<Test>:
do_default_tab: False
TabbedPanelItem:
text: 'page1'
RecycleView:
# size_hint: (None, None)
# size: (400, 400)
data: app.data
viewclass: Factory.Row
RecycleBoxLayout:
padding: 50, 50, 50, 50
orientation: 'vertical'
size_hint: 1, None
size: self.minimum_size
default_size_hint: 1, None
default_size: 0, dp(36)
<Row>:
spacing: 50
text: txtinpt.text
Label:
text: root.text
TextInput:
id: txtinpt
text: root.text
Button:
text: 'save'
on_press:
app.data[root.row_id]['text'] = root.text
""")
class Row(BoxLayout):
text = StringProperty()
row_id = NumericProperty()
class Test(TabbedPanel):
pass
class MyApp(App):
data = ListProperty()
def build(self):
self.data = [{'row_id': i, 'text': x} for i, x in enumerate(ROWS)]
test = Test()
return test
if __name__ == '__main__':
MyApp().run()