在构建期间从 kv 中的 kivy 文本输入获取值
Get value from kivy text input in kv during build
我有三个questions/problems:
- 下面给出了 app/app kv 文件的配置,为什么我必须在 ButtonsFactory class 中调用 self.build()。如果我删除它,我会黑屏,可能是因为 kv 文件中没有根元素,但如果我尝试制作 MainView 根元素,我最终也会出现黑屏。
- 第二个问题,是否可以在我的 someapp.kv 文件中设置自定义按钮的最小高度?它们绝不能小于 X。
- 最后但对我来说 最重要 为什么我无法从 class 函数 [=37= 中的 kv 文件中获取 TextInput 的文本 属性 ]()?解决此问题的最佳方法是什么?在 python 代码中硬编码这个值的全局变量?在 python 代码之前移动生成器(将 kv 作为字符串嵌入)?
- 最后一个问题...按钮 "fill" scrollview_id 我希望它们停止自我调整大小,而不是保留大小并在该视图中滚动。
someapp.py 文件
from kivy.app import App
from kivy.factory import Factory
from kivy.properties import ObjectProperty, StringProperty
# views
from kivy.uix.modalview import ModalView
# layouts
from kivy.uix.boxlayout import BoxLayout
import os
# defined in kv file.
class HeaderContainer(BoxLayout): pass
class ButtonsContainer(BoxLayout): pass
class MainView(ModalView): pass
class ButtonsFactory(BoxLayout):
target_location = StringProperty(None)
def __init__(self, *args, **kwargs):
super(ButtonsFactory, self).__init__(*args, **kwargs)
self.build() # Question 1: is that neccessary? (i think not, but black screen without it, why?)
def build(self):
self.orientation = "vertical"
for file_name in self.get_list_of_files():
btn = Factory.CustomButton()
with open(file_name, 'r') as test_file:
btn.file_name = test_file.readline().strip()[1:20]
btn.nice_name = file_name # Question 2: is it possible to set minimum height for kivy button? (havent found in api)
self.add_widget(btn)
# print ("1.!!!!!!", self.target_location) == NONE
@classmethod
def get_list_of_files(cls):
# print "2.!!!!!!", repr(cls.target_location) == <kivy.properties.StringProperty object at 0x7f1dd7596e20>
dir_ = "/tmp" #dir_ = cls.target_location
try:
files = [os.path.join(dir_, name) for name in os.listdir(dir_)
if os.path.isfile(os.path.join(dir_, name))]
except (OSError, IOError):
files = []
return files
class SomeApp(App):
def on_pause(self):
pass
def on_resume(self):
pass
def build(self):
return MainView()
if __name__ == '__main__':
SomeApp().run()
和someapp.kv文件
#:kivy 1.8.0
#:import platform platform
<CustomButton@Button>:
file_name: ''
nice_name: ''
text: root.nice_name + "\n" + root.file_name
halign:'center'
size_hint:(1, 0.1)
<HeaderContainer>:
id: header_layout
size_hint:(1, 0.1)
orientation:'horizontal'
# 2-nd-try # target_location: textinput_target_location.text
# I was trying here to pass by ObjectProperty (or StringProperty) but unfortunately failed.
TextInput:
size_hint:(0.7, 1)
id: textinput_target_location
multiline: False
hint_text: "path where stress files are stored, default /sdcard/appdir"
text: "/tmp" if platform.machine() in ["x86_64", "i686", "i386"] else "/sdcard/appdir/" # arm "arm7l", but also other arm's
#on_text: my_callback_to_reload_dir_contents()
Button:
size_hint:(0.2, 1)
id: read_target_location
text: "read target_location directory"
#on_release: my_callback_to_reload_dir_contents()
<ButtonsContainer>:
size_hint:(1, 0.9)
orientation:'vertical'
ScrollView:
id: scrollview_id
orientation: 'vertical'
ButtonsFactory
<MainView>:
BoxLayout:
# 1-st-try # target_location: HeaderContainer.target_location
id: main_layout
padding:10
spacing: 5
orientation:'vertical'
HeaderContainer
# n-th-try # target_location: HeaderContainer.target_location
ButtonsContainer
我会尽力解答您的问题:
1) 查看您的代码,ButtonsFactory
只是一个 BoxLayout
,它是一个用于容纳其他小部件的容器。 self.build
函数创建 CustomButton
小部件并将它们放入容器中。如果您不调用 self.build
,则不会向容器添加任何内容,并且您有一个空的(空白)BoxLayout
.
2) 这有点复杂,因为高度通常由装有小部件的容器控制。您可以通过将 size_hint
属性 设置为 None
并指定高度来手动设置小部件的高度。
3) 如果可以避免,我绝不会使用全局变量。在这种情况下,如果您只需要访问 TextInput 的文本内容,我会将它绑定到附加到您可以访问的小部件的 StringProperty
或 App 对象本身(可以在 .kv 中的任何位置访问)作为 app.<property>
.
4) 同样,高度由小部件所在的容器控制 (a BoxLayout
)。您可以通过在小部件上将 size_hint
设置为 None 来手动控制它们的大小。
另一个问题是您将 BoxLayout
(您的 ButtonsFactory
)放在 ScrollViewer
中。 BoxLayout
将自行调整大小以正好适合 ScrollViewer
的大小,因此它不会滚动。您需要通过清除 size_hint
来覆盖此行为。有关详细信息,请参阅 this SO question。
我有三个questions/problems:
- 下面给出了 app/app kv 文件的配置,为什么我必须在 ButtonsFactory class 中调用 self.build()。如果我删除它,我会黑屏,可能是因为 kv 文件中没有根元素,但如果我尝试制作 MainView 根元素,我最终也会出现黑屏。
- 第二个问题,是否可以在我的 someapp.kv 文件中设置自定义按钮的最小高度?它们绝不能小于 X。
- 最后但对我来说 最重要 为什么我无法从 class 函数 [=37= 中的 kv 文件中获取 TextInput 的文本 属性 ]()?解决此问题的最佳方法是什么?在 python 代码中硬编码这个值的全局变量?在 python 代码之前移动生成器(将 kv 作为字符串嵌入)?
- 最后一个问题...按钮 "fill" scrollview_id 我希望它们停止自我调整大小,而不是保留大小并在该视图中滚动。
someapp.py 文件
from kivy.app import App
from kivy.factory import Factory
from kivy.properties import ObjectProperty, StringProperty
# views
from kivy.uix.modalview import ModalView
# layouts
from kivy.uix.boxlayout import BoxLayout
import os
# defined in kv file.
class HeaderContainer(BoxLayout): pass
class ButtonsContainer(BoxLayout): pass
class MainView(ModalView): pass
class ButtonsFactory(BoxLayout):
target_location = StringProperty(None)
def __init__(self, *args, **kwargs):
super(ButtonsFactory, self).__init__(*args, **kwargs)
self.build() # Question 1: is that neccessary? (i think not, but black screen without it, why?)
def build(self):
self.orientation = "vertical"
for file_name in self.get_list_of_files():
btn = Factory.CustomButton()
with open(file_name, 'r') as test_file:
btn.file_name = test_file.readline().strip()[1:20]
btn.nice_name = file_name # Question 2: is it possible to set minimum height for kivy button? (havent found in api)
self.add_widget(btn)
# print ("1.!!!!!!", self.target_location) == NONE
@classmethod
def get_list_of_files(cls):
# print "2.!!!!!!", repr(cls.target_location) == <kivy.properties.StringProperty object at 0x7f1dd7596e20>
dir_ = "/tmp" #dir_ = cls.target_location
try:
files = [os.path.join(dir_, name) for name in os.listdir(dir_)
if os.path.isfile(os.path.join(dir_, name))]
except (OSError, IOError):
files = []
return files
class SomeApp(App):
def on_pause(self):
pass
def on_resume(self):
pass
def build(self):
return MainView()
if __name__ == '__main__':
SomeApp().run()
和someapp.kv文件
#:kivy 1.8.0
#:import platform platform
<CustomButton@Button>:
file_name: ''
nice_name: ''
text: root.nice_name + "\n" + root.file_name
halign:'center'
size_hint:(1, 0.1)
<HeaderContainer>:
id: header_layout
size_hint:(1, 0.1)
orientation:'horizontal'
# 2-nd-try # target_location: textinput_target_location.text
# I was trying here to pass by ObjectProperty (or StringProperty) but unfortunately failed.
TextInput:
size_hint:(0.7, 1)
id: textinput_target_location
multiline: False
hint_text: "path where stress files are stored, default /sdcard/appdir"
text: "/tmp" if platform.machine() in ["x86_64", "i686", "i386"] else "/sdcard/appdir/" # arm "arm7l", but also other arm's
#on_text: my_callback_to_reload_dir_contents()
Button:
size_hint:(0.2, 1)
id: read_target_location
text: "read target_location directory"
#on_release: my_callback_to_reload_dir_contents()
<ButtonsContainer>:
size_hint:(1, 0.9)
orientation:'vertical'
ScrollView:
id: scrollview_id
orientation: 'vertical'
ButtonsFactory
<MainView>:
BoxLayout:
# 1-st-try # target_location: HeaderContainer.target_location
id: main_layout
padding:10
spacing: 5
orientation:'vertical'
HeaderContainer
# n-th-try # target_location: HeaderContainer.target_location
ButtonsContainer
我会尽力解答您的问题:
1) 查看您的代码,ButtonsFactory
只是一个 BoxLayout
,它是一个用于容纳其他小部件的容器。 self.build
函数创建 CustomButton
小部件并将它们放入容器中。如果您不调用 self.build
,则不会向容器添加任何内容,并且您有一个空的(空白)BoxLayout
.
2) 这有点复杂,因为高度通常由装有小部件的容器控制。您可以通过将 size_hint
属性 设置为 None
并指定高度来手动设置小部件的高度。
3) 如果可以避免,我绝不会使用全局变量。在这种情况下,如果您只需要访问 TextInput 的文本内容,我会将它绑定到附加到您可以访问的小部件的 StringProperty
或 App 对象本身(可以在 .kv 中的任何位置访问)作为 app.<property>
.
4) 同样,高度由小部件所在的容器控制 (a BoxLayout
)。您可以通过在小部件上将 size_hint
设置为 None 来手动控制它们的大小。
另一个问题是您将 BoxLayout
(您的 ButtonsFactory
)放在 ScrollViewer
中。 BoxLayout
将自行调整大小以正好适合 ScrollViewer
的大小,因此它不会滚动。您需要通过清除 size_hint
来覆盖此行为。有关详细信息,请参阅 this SO question。