I am new to programming with Kivy, I'm trying to develop a program that collects the number of people in a room.
And my difficulty is to pass values between KV file and the main. I need to get the value of the slider which is in KV file and use it in main.py program
How could it? already I tried several ways that were posted on different topics here on the site but could not. Perhaps because as I have no knowledge in the area did not know apply it right.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, ObjectProperty
from kivy.lang import Builder
class ThemeBackground(Screen):
pass
class myApp(App):
def build(self):
root = ScreenManager()
root.add_widget(ThemeBackground(name='Screen'))
return root
if __name__ == '__main__':
myApp().run()
And Kv file
#:import random random.random
<ThemeBackground>:
orientation: 'vertical'
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
source: 'data/images/background.jpg'
size: self.size
BoxLayout:
padding: 10
spacing: 10
size_hint: 1, None
pos_hint: {'top': 1}
height: 44
Image:
size_hint: None, None
size: 24, 24
source: 'data/logo/kivy-icon-24.png'
Label:
height: 24
text_size: self.size
color: (1, 1, 1, .8)
text: 'Kivy 1.9.0.'
valign: 'middle'
GridLayout:
cols: 2
Label:
text: 'Please enter \nthe number of occupants?'
bold: True
font_name: 'data/fonts/DejaVuSans.ttf'
font_size: 22
halign: 'center'
Slider:
id: slider
min: 0.0
max: 15.0
value: 1.0
step: 1.0
orientation: "horizontal"
width: "38dp"
Label
text: ''
Label
text: '{}'.format(slider.value)
halign: 'center'
valign: 'top'
bold: True
text_size: self.size
font_size: 18
Button:
text: 'Enter'
size_hint_y: None
height: '50sp'}
You should load the kv file in the build of your myApp:
class myApp(App):
def build(self):
self.load_kv("main.kv")
return ThemeBackground()
You have unneeded } in the bottom of kv file,the last character, remove it.
height: '50sp'}
Preview:
In order to access the values of the slider, add a variable myslider to both of python and kv files like this:
kv:
<ThemeBackground>:
orientation: 'vertical'
myslider: slider
python:
class ThemeBackground(Screen):
myslider = ObjectProperty(None)
Now you can access the value , min or max by:
class myApp(App):
def build(self):
self.load_kv("kivy.3.kv")
tb = ThemeBackground()
print "value =",tb.myslider.value # <---- value here
print "min =",tb.myslider.min # <--- min here
return tb
Related
I´m learning kivy, and it has passed 3 weeks since i face this problem without encounter a solution, so i hope any of u guys could help me, i would appreciate it.
I have a main file:
from app import MyProgramApp
if __name__ == "__main__":
winapp = MyProgramApp()
winapp.run()
from where i start my app. Then i have a directory called "app", inside there is the following "init.py" file.
from kivy.app import App
from kivy.utils import QueryDict, rgba
from kivy.core.window import Window
from .view import MainWindow
Window.minimum_width = 500
Window.minimum_height = 650
Window.maximize()
class MyProgramApp(App):
colors = QueryDict()
colors.primary = rgba('#2D9CDB')
colors.secondary = rgba('#16213E')
colors.succes = rgba('#1FC98E')
colors.warning = rgba('#F2C94C')
colors.danger = rgba('#E85757')
colors.grey_dark = rgba('#C4C4C4')
colors.grey_light = rgba('#F5F5F5')
colors.black = rgba('#A1A1A1')
colors.white = rgba('#FFFFFF')
def build(self):
return MainWindow()
Same folder app, i have the following "view.py".
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager
class MainWindow(BoxLayout):
username = StringProperty("Usuario")
def __init__(self, **kw):
super().__init__(**kw)
def on_press_home(self):
self.ids.scrn_mngr.current = "scrn_home"
class ViewManager(ScreenManager):
def __init__(self, **kw):
super().__init__(**kw)
class NavTab(ToggleButtonBehavior, BoxLayout):
text = StringProperty('')
icon = StringProperty('')
def __init__(self, **kw):
super().__init__(**kw)
and finally for that folder i have "myprogram.kv"
#:kivy 2.1.0
#:import Home views.home.Home
<MainWindow>:
spacing: dp(8)
canvas.before:
Color:
rgba: app.colors.white
Rectangle:
pos: self.pos
size: self.size
# NAVIGATION BAR
BoxLayout:
id: nav_menu
size_hint_x: .2
orientation: "vertical"
size_hint_min_x: dp(100)
# LOGO
BoxLayout:
id: logo_nbox
size_hint_y: .1
size_hint_min_y: dp(70)
padding: dp(16)
AnchorLayout:
anchor_x: "right"
size_hint_x: None
width: dp(52)
halign: "left"
Label:
text: "COMPANY"
halign: "center"
BoxLayout:
orientation: "vertical"
Label:
text: "COMPANY"
halign: "center"
Label:
text: "Phrase"
halign: "center"
# OPTIONS
GridLayout:
id: tabs_box
cols: 1
spacing: dp(4)
size_hint_y: .5
canvas.before:
Color:
rgba: app.colors.grey_dark
Rectangle:
pos: self.pos
size: [self.size[0], dp(1)]
NavTab:
text: "Home"
state: "down"
on_press: root.on_press_home()
# BODY
BoxLayout:
size_hint_x: .8
spacing: dp(8)
orientation: "vertical"
padding: [dp(16), dp(8), dp(12), dp(8)]
canvas.before:
Color:
rgba: app.colors.grey_light
Rectangle:
pos: self.pos
size: self.size
# SCREENS
BoxLayout:
ViewManager:
id: scrn_mngr
<ViewManager>:
Screen:
name: "scrn_home"
Home:
id: home
<NavTab>:
background_normal: ""
background_down: ""
background_color: [0,0,0,0]
group: "tabs"
size_hint_y: None
height: dp(45)
spacing: dp(4)
canvas.before:
Color:
rgba: [0,0,0,0] if self.state == "normal" else rgba("#E1F1FF")
Rectangle:
pos: self.pos
size: self.size
Color:
rgba: [0,0,0,0] if self.state == "normal" else app.colors.primary
Rectangle:
pos: [self.pos[0]+self.size[0]-dp(1), self.pos[1]]
size: [dp(8), self.size[1]]
Label:
halign: "left"
valign: "middle"
text: root.text
color: app.colors.grey_dark if root.state == "normal" else app.colors.primary
Then i got another folder called "views" inside i have another folder called "home", inside home we encounter 3 files "init.py", "home.kv", "home.py". the first one "init.py" is the following.
from .home import Home
then we got "home.kv".
#:kivy 2.1.0
<Home>:
orientation: "vertical"
Label:
size_hint_y: .1
text: "Other"
Button:
size_hint_y: .1
text: "popup"
on_press: root.open_popup()
BoxLayout:
size_hint_y: .8
id: home_box
<SomePopup>:
title: "SOME TITLE"
title_align: "center"
title_color: app.colors.primary
size_hint: .25, .8
size_hint_min_x: dp(200)
pos_hint: {"x": .1, "top": .9}
BoxLayout:
orientation: "vertical"
padding: [dp(0), dp(12), dp(0), dp(12)]
Label:
text: "Some text"
Button:
text: "create buttons on box"
on_press: root.modify_home_box()
and finally and the problem that i´m facing is whit the following file "home.py"
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.app import App
Builder.load_file('views/home/home.kv')
class Home(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def open_popup(self):
Factory.SomePopup().open()
class SomePopup(Popup):
def __init__(self, **kw):
super().__init__(**kw)
def modify_home_box(self):
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
custom_button = Button(
text = "something"
)
my_box.add_widget(custom_button)
That i´m trying to do is actually modify "home_box" with is store on ids Home dictionary, i also try with ObjectProperty (but that gives and Attribute Error, since i only could read propertys but doesnt modify it), instance of a new Home class doesnt work... searching for current app in App appear doesnt work since Home is store i think on screenManager...
I need add a button or some widget to "home_box" from outside class "SomePopup". I also drop here a repository on github with the whole code. github_repo
I don't know how to solve my issue, and i try with the resources available here on stack as well other net places... any help would be appreciate.
Just a very complicated path to the widget of interest. In your modify_home_box() method, try replacing:
my_app = App.get_running_app().root
my_box = my_app.ids.home.ids.home_box
with:
my_app = App.get_running_app().root
my_box = my_app.ids.scrn_mngr.ids.home.ids.home_box
I'm creating a simple Database-GUI and want to add two lines to a form. each line is a DataField-Object, and contains a label and a TextInput organised by a horizontal Boxlayout. up to here all fine.
The Form-Widget contains also a BoxLayout (Orientaton: "Vertical") organizing the two DataField-Objects by listing them up under each other, but it doesn't work...
My Question: WHY??? and how can I fix it?
dbgui3.py
from kivy import require
require("2.0.0")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty, ObjectProperty
class DataField(Widget):
title = StringProperty()
pass
class Form(Widget):
b = ObjectProperty()
def __init__(self, *rec, **kwargs):
super().__init__()
for df in rec:
self.b.add_widget(DataField(title=df))
class DbGui3(App):
def build(self):
return Form("hello", "world")
if __name__ == '__main__':
DbGui3().run()
dbgui3.kv
<DataField>:
text: txt.text
BoxLayout:
orientation: "horizontal"
size_hint: None, None
size: root.width, 30
canvas:
Color:
rgb: 0.2,0.2,0.2
Rectangle:
size: self.size
Label:
text: root.title
size_hint: None, 1
width: self.texture_size[0]
TextInput:
id:txt
multiline: False
on_text_validate: print("text validated:" + root.text)
<Form>:
b:b
BoxLayout:
id: b
orientation: "vertical"
size_hint: None, None
size: root.width, root.height
canvas:
Color:
rgb: 0.1,0.2,0.3
Rectangle:
size: self.size
The problem is that you are using Widget as a base class for your DataField and Form classes. The Widget class does not take any notice of things like size_hint, pos_hint, and others. It is not intended to be a Layout. I suggest you use BoxLayout as the base for your DataField and some other Layout (perhaps FloatLayout) as the base class for Form. Using this suggestion, your class definitions could be:
class DataField(BoxLayout):
title = StringProperty("example")
class Form(FloatLayout):
pass
Then modifying your kv:
<DataField>:
size_hint: 1, None
height: 30
orientation: "horizontal"
Label:
size_hint: None, None
size: self.texture_size[0]*1.3, root.height
text: root.title
TextInput:
multiline: False
on_text_validate: print(root.title)
<Form>:
BoxLayout:
orientation: "vertical"
size_hint: None, None
size: root.width/2, root.height/2
DataField:
title: "hello"
DataField:
title: "world"
I think this will do what you want.
I'm pretty new to python and kivy and I'm trying to build my first app for my masterthesis. The problem I'm struggeling with right now is that I have multiple python and kivy files, and my app includes a group of Toggle buttons and Spinners. I want to 'store'/assign theselected values and print them when i hit my submit button. I'm working with multiple python and kivy files. The app also has some sliders and i managed to get those values when pressing submit, but can't figure it out for toggles nor spinners. I hope you can help!:)
Main .py, rather important:
import kivy
from kivy.app import App
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.properties import ObjectProperty
Builder.load_file('Header.kv')
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
#Layout
class Peenomat(AnchorLayout):
def show_selected_value(self, spinner, text):
print(spinner, text)
#pass
#DropDown in Inputparameters
#class InputParameters(BoxLayout):
#state = BooleanProperty(False)
class PeenomatApp(App):
def build(self):
return Peenomat()
if __name__=="__main__":
PeenomatApp().run()
The main kv file:
AnchorLayout:
anchor_x: 'left'
anchor_y: 'bottom'
GridLayout:
cols: 1
canvas.before:
Color:
rgba: 0.75 ,0.75, 0.75, 1
Rectangle:
pos: self.pos
size: self.size
Header:
id: _header
size_hint: 1, 0.1
#height: 100
InputParameters:
id:_input_parameters
size_hint: 1, 0.45
StatusBar:
id:_status_bar
size_hint: 1, 0.1
#height: 50
OutputParameters:
id:_output_parameters
size_hint: 1, 0.35
The .kv file that includes the toogle buttons, spinners, and sliders where i guess most of the implemantation needs to be done
#: import statusbar StatusBar
<InputParameters#GridLayout>
prozess: _proz_value
prozess1: _prozess1
prozess2: _prozess2
prozess3: _prozess3
vorbehandlung: _vorbehandlung
material: _material
haerte: _haerte
rauheit: _rauheit
cols: 2
padding: 15
spacing: 15
#Farbe Schrift Label
cb: (1,1, 1,1)
#Farbe Slider
cs: (0,0.353, 0.663,1)
#FontSize
fs: 20
#Prozess
Label:
text:'Prozess: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'horizontal'
id: _proz_value
_proz_value: 0
ToggleButton:
text:'P-MOH'
id: _prozess1
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 1
ToggleButton:
text:'E-MOH'
id: _prozess2
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 2
ToggleButton:
text:'PE-MOH'
id: _prozess3
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 3
#Material
Label:
text: 'Material: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
Spinner:
id: _material
# Callback
on_text:
text: "Auswahl treffen"
bold:True
values: ['1.2379', 'Gusseisen', 'Kautschuk', 'Carbon', 'Adamantium']
#background_normal: '[1,1,1,1]'
background_color: root.cs
color: root.cb
# Herstellschritte
Label:
text:'Fertigungsschritte: '
bold: 'True'
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
Spinner:
id: _vorbehandlung
# Callback
on_text:
app.root.show_selected_value(self, self.text)
text: "Auswahl treffen"
bold:True
values: ['Fräsen', 'Erodieren', 'Schleifen', 'Polieren']
#background_normal: '[1,1,1,1]'
background_color: root.cs
color: root.cb
# Haerte
Label:
text:'Haerte: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'vertical'
spacing: 15
Label:
text: str(_haerte.value) + ' HRC'
color: root.cs
bold: True
Slider:
id: _haerte
min: 45
max: 65
value:55
step: 1
value_track: True
value_track_color: root.cs
# Rauheit
Label:
text:'Rauheit: '
#color: cb
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'vertical'
spacing: 15
Label:
text: str("%.1f" % _rauheit.value) + ' Rz' #eine Nachkommastelle
color: root.cs
bold: True
Slider:
id: _rauheit
min: 1
max: 10
value:5.5
step: 0.1
value_track: True
value_track_color: root.cs
The .kv file that includes the submit button:
#: import statusbar StatusBar
<StatusBar#BoxLayout>
orientation:'horizontal'
padding: 5
fs: 16
Button:
text: 'Clear'
background_color: 0.0, 0.353, 0.663, 1.0
size_hint: 0.4, 1
bold: True
font_size: 20
on_press: root.btn_clear()
Button:
text: 'Submit'
background_color: 0.0, 0.353, 0.663, 1.0
size_hint: 0.4, 1
bold: True
font_size: 20
on_press: root.btn_submit()
and last but not the least the file that includes the methods that are assigned to the buttons, which shuld also be important for my issue:
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.app import App
from kivy.lang import Builder
class StatusBar(BoxLayout):
group_mode = False
#translation = ListProperty(None)
prozess = ObjectProperty(None)
vorbehandlung = ObjectProperty(None)
material = ObjectProperty(None)
haerte = ObjectProperty(None)
rauheit = ObjectProperty(None)
def btn_submit(self,text):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text)
def btn_clear(self):
np = App.get_running_app().root.ids._input_parameters
np.prozess1.state = "normal"
np.prozess2.state = "normal"
np.prozess3.state = "normal"
np.material.text = "Auswahl treffen"
np.haerte.value = 55
np.rauheit.value = 5.5
The App is running like this and the clear button is exactly doing what its supposed to do, but I really can't figure out how I manage to print the selected spinner and toggle values when hitting submit...I hope you guys can help, been struggeling with this since a while now. Thanks in advance!
Alright i figured out an easy way to get the spinner value when hititng submit:
def btn_submit(self):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text, "Vorbehandlung:", ip.vorbehandlung.text)
to get the value of the toggle buttons i did this:
def on_state(self, togglebutton):
tb = togglebutton
if tb.state == 'down':
self.verfahren = tb.text
InputParameters.verfahren = tb.text
print(self.verfahren)
return InputParameters.verfahren
and added in the .kv file for the toggle button:
ToggleButton:
id:_prozess2
text:'E-MOH'
on_state: root.on_state(self)
I'm getting the value/state like that, but it's not triggered with the submit button, can't figure out how to do so
I am trying to display the value of a slider on a different screen. i have tried this(below code) but for some reason, the value doesn't seem to show up. the code runs fine but no value is returned. Thanks for your help :) Cheers.
temperature screen
here is a snippet of the python code:
class Thermostat(Screen):
label = StringProperty()
def display(self):
tempVal = self.label
return str(tempVal)
and the kv files:
<Thermostat>:
name: "thermostat"
BoxLayout:
orientation: 'horizontal'
cols: 2
Label:
id: label
font_size: "11sp"
text: "INSIDE: " + root.display()
Label:
text: "More Info"
font_size: "11sp"
kv file 2:This screen holds the true value from the slider, i am trying to pass that value to the Thermostat screen.
<Temperature>:
BoxLayout:
size_hint_y: None
height: '48dp'
cols: 3
Label:
text: 'THERMOSTAT'
Slider:
id: temp
min: 40
max: 100
value: 1
step: 1
on_value: app.root.get_screen('thermostat').label = str('{}'.format(temp.value))
Label:
id: slide_val
text: '{}'.format(temp.value)
root.display is only called once, at the beginning of the program. For it to work well, every time you change the value of the slider root.display should be called.
However, it is very simple to do this using propertis in kv languaje:
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang.builder import Builder
Builder.load_string('''
<Manager>:
id: manager
Thermostat:
id: thermostat
name: 'thermostat'
manager: 'screen_manager'
temp: temperature.temp #<<<<<<<<<<<<
Temperature:
id: temperature
name: 'temperature'
manager: 'screen_manager'
<Thermostat>:
temp: 0 #<<<<<<<<<<<<
BoxLayout:
orientation: 'horizontal'
cols: 3
Label:
id: label
font_size: "11sp"
text: "INSIDE: {}".format(root.temp) #<<<<<<<<<<<<
Label:
text: "More Info"
font_size: "11sp"
Button:
text: ">"
on_release: app.root.current= "temperature"
size_hint_x: None
width: 30
<Temperature>:
temp: temp_slider.value #<<<<<<<<<<<<
BoxLayout:
cols: 4
Button:
text: "<"
on_press: app.root.current = "thermostat"
size_hint_x: None
width: 30
Label:
text: 'THERMOSTAT'
Slider:
id: temp_slider
min: 40
max: 100
value: 40
step: 1
Label:
id: slide_val
text: str(root.temp)
''')
class Thermostat(Screen):
pass
class Temperature(Screen):
pass
class Manager(ScreenManager):
pass
class ExampleApp(App):
def build(self):
return Manager()
if __name__ == "__main__":
ExampleApp().run()
If you want to use the slider's value in your class Temperature, simply declare the property in the class:
from kivy.properties import NumericProperty
class Temperature(Screen):
temp = NumericProperty()
def __init__(self, **kwargs):
super(Temperature, self).__init__(**kwargs)
I am new to kivy wanted to know how we can bind textinput box to suggestion so that user and touch and select the suggestions.
I have long list of buttons out of which i want to select on the basis of name.
i am using kivymd i dont real know how to do it in kivy but here are the codes for kivymd
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.screenmanager import Screen
from kivymd.icon_definitions import md_icons
from kivymd.app import MDApp
from kivymd.uix.list import OneLineIconListItem
Builder.load_string(
'''
#:import images_path kivymd.images_path
<CustomOneLineIconListItem>:
IconLeftWidget:
icon: root.icon
<PreviousMDIcons>:
BoxLayout:
orientation: 'vertical'
spacing: dp(10)
padding: dp(20)
BoxLayout:
size_hint_y: None
height: self.minimum_height
MDIconButton:
icon: 'magnify'
MDTextField:
id: search_field
hint_text: 'Search icon'
on_text: root.set_list_md_icons(self.text, True)
RecycleView:
id: rv
key_viewclass: 'viewclass'
key_size: 'height'
RecycleBoxLayout:
padding: dp(10)
default_size: None, dp(48)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
'''
)
class CustomOneLineIconListItem(OneLineIconListItem):
icon = StringProperty()
class PreviousMDIcons(Screen):
def set_list_md_icons(self, text="", search=False):
'''Builds a list of icons for the screen MDIcons.'''
def add_icon_item(name_icon):
self.ids.rv.data.append(
{
"viewclass": "CustomOneLineIconListItem",
"icon": name_icon,
"text": name_icon,
"callback": lambda x: x,
}
)
self.ids.rv.data = []
for name_icon in md_icons.keys():
if search:
if text in name_icon:
add_icon_item(name_icon)
else:
add_icon_item(name_icon)
class MainApp(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.screen = PreviousMDIcons()
def build(self):
return self.screen
def on_start(self):
self.screen.set_list_md_icons()
MainApp().run()
some results
here is the screen shot result when your not searching for anything
here is a screen shot when i am trying to search
second
here is a result when the word am searching does not exist
Here is a simple example that will use the use text input to search in the option_list and will display the suggestion under the text input widget.
I used the kivymd widget to get a nice look design you replaced with the normal kivy widgets if you want
from kivy.properties import ListProperty
from kivymd.app import MDApp
from kivymd.uix.list import OneLineAvatarIconListItem
from kivymd.uix.textfield import MDTextField
kv = """
Screen:
BoxLayout:
orientation: 'vertical'
spacing: 1
BoxLayout:
size_hint_y: 1/5
canvas.before:
Color:
rgba: 0, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size[0], 2
MDIconButton:
icon: 'magnify'
size_hint_y: 1
SearchTextInput:
id: Search_TextInput_id
size_hint_y: .97
pos_hint:{ 'left':0 , 'top': 1}
hint_text: 'search'
hint_text_color: 1,1,1,1
icon_left: 'magnify'
mode: "fill"
helper_text_mode: "persistent"
helper_text: "Search"
line_color: [1,1,1,1]
color_normal: [1,1,1,1]
font_size: .35 * self.height
active_line: False
multiline: False
MDIconButton:
icon: 'close'
size_hint_y:1
text_color: 0,0,0,1
BoxLayout:
orientation: 'vertical'
padding: 4
RecycleView:
viewclass: 'Search_Select_Option'
data:app.rv_data
RecycleBoxLayout:
spacing: 15
padding : 10
default_size: None, None
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
<Search_Select_Option>:
on_release: print(self.text)
IconRightWidget:
icon: "arrow-top-left"
"""
class Search_Select_Option(OneLineAvatarIconListItem):
pass
class SearchTextInput(MDTextField):
option_list = 'one1,two1,two2,three1,three2,three3,four1,four2,four3,four4,five1,five2,five3,five4,five5'.split(',')
def on_text(self, instance, value):
app = MDApp.get_running_app()
option_list = list(set(self.option_list + value[:value.rfind(' ')].split(' ')))
val = value[value.rfind(' ') + 1:]
if not val:
return
try:
app.option_data = []
for i in range(len(option_list)):
word = [word for word in option_list if word.startswith(val)][0][len(val):]
if not word:
return
if self.text + word in option_list:
if self.text + word not in app.option_data:
popped_suggest = option_list.pop(option_list.index(str(self.text + word)))
app.option_data.append(popped_suggest)
app.update_data(app.option_data)
except IndexError:
pass
class RVTestApp(MDApp):
rv_data = ListProperty()
def update_data(self, rv_data_list):
self.rv_data = [{'text': item} for item in rv_data_list]
print(self.rv_data, 'update')
def build(self):
return Builder.load_string(kv)
RVTestApp().run()
Incase anyone is wondering how can get the value of the selected item from the list, I have a little updated version here:
from kivymd.icon_definitions import md_icons
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.list import OneLineListItem
from kivy.uix.screenmanager import Screen
KV = '''
<ListSelect>
BoxLayout:
orientation: 'vertical'
spacing: dp(10)
padding: dp(20)
pos_hint:{'center_x': 0.5, 'y': 0.85}
BoxLayout:
size_hint_y: None
height: self.minimum_height
MDIconButton:
icon: 'magnify'
MDTextField:
id: search_field
hint_text: 'Search icon'
on_text:
root.set_list(self.text)
RecycleView:
pos_hint:{'center_x': 0.5, 'center_y': 0.4}
MDList:
id: container
'''
class ListSelect(Screen):
def pressed(self, value):
# value here is the OneLineListItem
self.ids.container.clear_widgets()
# set TextField text to selected list item
self.ids.search_field.text = value.text
print(value.text)
def set_list(self, text=" "):
# text defaults to blank space to not show any icons initally
# each OneLineListItem takes the pressed func on press
self.ids.container.clear_widgets() # refresh list
for icon in md_icons.keys():
# using casefold() to make the input case insensitve
if icon.startswith(text.casefold()):
self.ids.container.add_widget(
OneLineListItem(text=icon, on_press=self.pressed)
)
class Test(MDApp):
def build(self):
Builder.load_string(KV)
self.screen = ListSelect()
return self.screen
def on_start(self):
self.screen.set_list()
Test().run()
One catch: the search needs quite a long time to finish. If anyone has any hints on how to speed it up, you are very welcome!