How can I detect selected checkbox with kivy - python

Thanks to this code, I can create interface to present a List of information.
However, I need to create a function when I click the button "save" I print all text item selected in CheckBox
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.list import ILeftBodyTouch, TwoLineAvatarIconListItem
from kivymd.uix.selectioncontrol import MDCheckbox
KV = """
<ListItemWithCheckbox>:
RightCheckbox:
BoxLayout:
ScrollView:
MDList:
id: scroll
MDRaisedButton:
text: "Save"
"""
class ListItemWithCheckbox(TwoLineAvatarIconListItem):
"""Custom list item."""
class RightCheckbox(ILeftBodyTouch, MDCheckbox):
"""Custom right container."""
class MainApp(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
for i in range(15):
self.root.ids.scroll.add_widget(
ListItemWithCheckbox(text=f"Item {i}", secondary_text=f"Item {i+10}")
)
MainApp().run()

You can do that by defining a method in your App:
def save_checked(self):
mdlist = self.root.ids.scroll # get reference to the MDList
for wid in mdlist.children:
if isinstance(wid, ListItemWithCheckbox): # only interested in the ListItemWithCheckboxes
cb = wid.ids.cb # use the id defined in kv
if cb.active: # only print selected items
print(wid.text, wid.secondary_text)
Then modify kv to call that method on Button release:
MDRaisedButton:
text: "Save"
on_release: app.save_checked()
and add the id for the RightCheckbox in the kv:
<ListItemWithCheckbox>:
RightCheckbox:
id: cb

Related

how to Create Dropdown list for next window in Kivy

how do I create Dropdown list in the next window after clicking button in the first screen, I tried to initiate the button in the kv file just to have a button in the ModelWindow screen but the next problem is the button variable in ModelWindow class is gone. the button variable is needed for the lista method in order to activate dropdown
Python File
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
class ModelWindow(Screen):
def window(self):
box = BoxLayout(orientation='vertical')
label = Label(text='LABEL')
button = Button(text='Selecione', font_size=30, size_hint_y=0.15, on_release=self.lista)
box.add_widget(label)
box.add_widget(button)
self.dropdown = DropDown() # Create the dropdown once and keep a reference to it
self.dropdown.bind(on_select=lambda instance, x: setattr(button, 'text', x))
for index in range(10): # create the buttons once
btn = Button(text='Value %d' % index, size_hint_y=None, height=44,
on_release=lambda btn: print(btn.text)) # bind every btn to a print statement
btn.text = 'Value %d' % index
btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))
self.dropdown.add_widget(btn)
return box
def lista(self, button):
# dropdown = DropDown() <---- DON'T NEED THIS
# button.bind(on_release=self.dropdown.open) <---- DON'T NEED THIS
self.dropdown.open(button) # you need this to open the dropdown
# print(button.text)
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file("proj.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
Kv file
WindowManager:
MainWindow:
SecondWindow:
ModelWindow:
<ModelWindow>:
name: "model"
<MainWindow>:
name: "main"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Button:
text: "Select Model"
on_press:
app.root.current = "model"
Button:
text: "Test Model"
Button:
text: "Create New Model"
on_release:
app.root.current = "second"
root.manager.transition.direction = "left"
<SecondWindow>:
name: "second"
Button:
text: "Go Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
My I ask if anyone knows how to make a dropdown list in the next window? should I write it in the kv file or the python itself? Thank youu
If I get your point correctly, you want to initialize the ModelWindow class. In order to do that you can simply call the method window in __init__ with some modifications or define everything directly in __init__ as,
def __init__(self, **kwargs):
super().__init__(**kwargs)
box = BoxLayout(orientation='vertical')
label = Label(text='LABEL')
...
# Same as in your method `window`.
...
self.dropdown.add_widget(btn)
self.add_widget(box)

cannot remove widget in Kivy

i cannot remove widget using the screen with kivy python, i dont know why it just does not do anything
the code was suppose to remove textinput with id:name on the first screen but it just does not do anything and no error message.
here is all of the code it is tested on python 3.7.4, kivy 1.11.1 on window.
module_media_player.py
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.core.audio import SoundLoader
from kivy.uix.videoplayer import VideoPlayer
from kivy.uix.screenmanager import ScreenManager,Screen
class Player(Screen):
def press(self):
self.ids.name.text = 'nice'
def remove(self):
self.remove_widget(self.ids.name)
class MediaPlayer(Screen):
pass
class WindowManager(ScreenManager):
pass
kv = Builder.load_file('my.kv')
class GoodApp(App):
def build(self):
return kv
if __name__ == '__main__':
GoodApp().run()
my.kv
WindowManager:
Player:
MediaPlayer:
<Player>:
name:"player"
BoxLayout:
orientation:"vertical"
size:root.width,root.height
cols:2
TextInput:
id:name
multiline:False
text:"first"
font_size:12
size_hint_y:0.3
Button:
text:"click me"
on_press:root.remove()
Button:
text:"next window"
font_size:14
size_hint_y:0.7
on_release:
app.root.current = "mediaplayer"
root.manager.transition.direction = "left"
<MediaPlayer>:
name:"mediaplayer"
BoxLayout:
orientation:"vertical"
size:root.width,root.height
Label:
text:"second"
font_size:12
Button:
text:"previous window"
font_size:14
on_release:
app.root.current = "player"
root.manager.transition.direction = "right"
Your code:
def remove(self):
self.remove_widget(self.ids.name)
is trying to remove the TextInput from the Player Screen, but that Textinput is not a child of Player. It is actually a child of the BoxLayout. You can fix this by modifying your remove() method:
def remove(self):
textinput = self.ids.name
textinput.parent.remove_widget(textinput) # remove widget from its parent

How to insert value of List Item into another Screen in KivyMD

In the app I'm coding on button click on the bottom right of the screen there appears a popup window. On "Done" click the popup window closes (close_dialog method), and a new List Item appears. The text of the List Item is obtained from MDTextField of the popup. On List Items click we enter another screen <GroupScreen> (goto_group method).
So I have two questions:
As far as I understand if we make several List Items, they all lead to one instance of <Group Screen>. Am I right?
I want each of created List Items to lead to its unique <GroupScreen> instance. For example, I want List text to be copied to MDLabel (instead of "Welcome" text). How can I do that?
Code .py:
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.textfield import MDTextField
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import Screen, ScreenManager
from kivymd.uix.list import TwoLineAvatarListItem
Window.size = (288, 511)
sm = ScreenManager()
class GroupScreen(Screen):
pass
class DialogContent(BoxLayout):
pass
class MainScreen(Screen):
dialog = None
def show_dialog(self, *args):
'''
Create group creation popup
'''
if not self.dialog:
self.dialog = MDDialog(
title="Create new group",
type="custom",
content_cls=DialogContent(),
)
self.dialog.open()
def close_dialog(self, *args):
'''
Close popup on Done click
'''
self.dialog.dismiss()
self.new_window()
def new_window(self, *args):
'''
Create new group button
'''
mylist = TwoLineAvatarListItem(text = self.dialog.content_cls.textfield.text,
on_release = self.goto_group)
self.mdlist.add_widget(mylist)
def goto_group(self, *args):
sm.current = 'group'
class grudget4App(MDApp):
def build(self):
sm.add_widget(MainScreen(name='main'))
sm.add_widget(GroupScreen(name='group'))
scroll = ScrollView()
return sm
if __name__ == '__main__':
grudget4App().run()
Code. kv:
ScreenManager:
MainScreen:
GroupScreen:
<DialogContent>:
textfield: textfield
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField:
id: textfield
hint_text: "Group name"
MDFlatButton:
id: btn1
text: "Done"
text_color: self.theme_cls.primary_color
on_release: app.root.get_screen('main').close_dialog()
<MainScreen>:
name: 'main'
mdlist: mdlist
FloatLayout:
size_hint: 1, 0.89
ScrollView:
MDList:
id: mdlist
MDFloatingActionButton:
pos_hint: {'right': 0.95, 'y': 0.05}
icon: "icon.png"
theme_text_color: "Custom"
text_color: app.theme_cls.primary_color
on_release:
root.show_dialog()
<GroupScreen>:
name: 'group'
MDLabel:
text: "Welcome" #app.root.ids["textfield"].text
halign: 'center'
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
on_release:
root.manager.current = 'main'
From the documentation:
name
Name of the screen which must be unique within a ScreenManager.
I don't see any code creating new GroupScreens, but wherever you put that code, you must include a unique name="some_group_name" for it.
I my experience, in order to allow Buttons to operate in an MDDialog, you must add auto_dismiss=False to its declaration:
def show_dialog(self, *args):
'''
Create group creation popup
'''
if not self.dialog:
self.dialog = MDDialog(
text="Create new group",
type="custom",
auto_dismiss=False, # needed to allow Buttons to operate
content_cls=DialogContent(),
)
self.dialog.open()
Then, the new_window() method can create the new GroupScreen and the Button:
def new_window(self, *args):
'''
Create new group button
'''
group_name = self.dialog.content_cls.textfield.text
mylist = TwoLineAvatarListItem(text=group_name,
on_release = partial(self.goto_group, group_name)) # use partial to pass group name
self.mdlist.add_widget(mylist)
sm.add_widget(GroupScreen(name=group_name)) # actually create the new GroupScreen and add it
And the goto_group() method becomes:
def goto_group(self, group_name, *args):
sm.current = group_name # switch current screen to the passed in group
The App declaration can be:
class grudget4App(MDApp):
def build(self):
sm.add_widget(MainScreen(name='main'))
# sm.add_widget(GroupScreen(name='group'))
# scroll = ScrollView()
return sm
Note the above requirement for unique name for Screens. You should take care that the user doesn't create duplicate group names.

Kivy: Update TextInput after picking value from Spinner or Dropdown

Im trying to create GUI with kivy but can't figure this.Created Popup screen and trying to pick value from dropbox and add this value to my TextInput.
test.py:
from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.dropdown import DropDown
from kivy.uix.spinner import Spinner
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
class MyDropDown(DropDown):
def on_select(self, data):
print('Selected value:',data)
#Lets add this data to TextInput ?
MyTextInput.text = data
#Lets check is that actual text ?
print('MyTextInput.text is:',MyTextInput.text)
#HOW CAN I ADD THIS TEXT TEXTINPUT AFTER THAT?
class MySpinner(Spinner):
dropdown_cls = ObjectProperty(MyDropDown)
class MyTextInput(TextInput):
pass
class MyTestPopup(Popup):
my_popup_spinner = ObjectProperty()
my_textinput_id = ObjectProperty()
class TestPage(Screen):
MypagePopup = ObjectProperty()
def open_my_popup(self, *args):
#Lets create my popup
self.MypagePopup = MyTestPopup()
self.MypagePopup.my_popup_spinner.values = ['Test1','Test2','Test3','Test4','Test']
self.MypagePopup.open()
class TestPageManager(ScreenManager):
pass
class test(App):
def build(self):
return TestPageManager()
if __name__=='__main__':
test().run()
test.kv:
<TestPageManager>:
TestPage:
name: 'mainpagename'
<MySpinner>:
text: 'Pick Value'
<MyDropDown>:
values: ['Test1','Test2','Test3','Test4','Test5']
<MyTextInput>:
<MyTestPopup>:
my_popup_spinner : my_popup_spinner
my_textinput_id : my_textinput_id
BoxLayout:
orientation: 'vertical'
Label:
text: 'Testing Label Area..'
pos: self.pos
size: self.size
MyTextInput:
id: my_textinput_id
MySpinner:
id: my_popup_spinner
Button:
text: 'Done'
on_release:
print('MyTextInput id is :',my_textinput_id.text)
<TestPage>:
Button:
text: 'Open Popup'
on_release: root.open_my_popup()
As you can see I created like that GUI.
But can't update TextInput after pick from spinner.How can i update this textinput after pick value from dropbox.I can't figure it out.I think i correctly describe my problem. Thanks for reading and answering.
kv = "Spinner:
on_text:
my_textinput_id.text = my_popup_spinner.text"
did this in my kv string for Builder.load_string(kv)and it works for me
you can try and implement it in you code example and see if it works.
set the id.text of the textinput = to my spinner id.text in the on_text: event of the Spinner

How to get Id and Text value of a kivy button as string?

I have an app with multiple buttons and I need to get id and text value of the button as string when it is pressed. The grabbed Ids and Text valus of the button will then be passed to another function for further processing. For simplicity I wrote this sample programme.
# main.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
########################################################################
class KVMyHBoxLayout(BoxLayout):
pass
########################################################################
class ExampleApp(App):
def Pressbtn(self, *args):
print'Pressed button'
#----------------------------------------------------------------------
def build(self):
return KVMyHBoxLayout()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = ExampleApp()
app.run()
kv file
<MyButton#Button>:
color: .8,.9,0,1
font_size: 32
<KVMyHBoxLayout>:
orientation: 'vertical'
MyButton:
id:"idBtn1"
text: "Btn1"
background_color: 1,0,0,1
on_press:app.Pressbtn()
MyButton:
id:"idBtn2"
text: "Btn2"
background_color: 0,1,0,1
on_press:app.Pressbtn()
Label:
text: "ID"
background_color: 0,0,1,1
Label:
text: "Text"
background_color: 1,0,1,1
When a button is pressed its corresponding values of id and text will be shown in the ID and Text labels. Currently the above code only print Pressed button when button is pressed. I want to know how to get id and text value of button pythonically.
First, you must pass the button instance explicitly to the method when it is called from the kv:
on_press: app.Pressbtn(self)
You can then use the instance reference to modify the button or see its attributes, you do not need the id. If you want to get the id, you can only do it using the ids dictionary of the button parent.
An example based on your code:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
kv_file = '''
<MyButton#Button>:
color: .8,.9,0,1
font_size: 32
<KVMyHBoxLayout>:
orientation: 'vertical'
MyButton:
id:"idBtn1"
text: "Btn1"
background_color: 1,0,0,1
on_press:app.Pressbtn(self)
MyButton:
id:"idBtn2"
text: "Btn2"
background_color: 0,1,0,1
on_press:app.Pressbtn(self)
Label:
id: lobj
text: "Object"
background_color: 1,0,1,1
Label:
id: lid
text: "ID"
background_color: 0,0,1,1
Label:
id: ltext
text: "Text"
background_color: 1,0,1,1
'''
class KVMyHBoxLayout(BoxLayout):
pass
class ExampleApp(App):
def Pressbtn(self, instance):
instance.parent.ids.lobj.text = str(instance)
instance.parent.ids.ltext.text = instance.text
instance.parent.ids.lid.text= self.get_id(instance)
def get_id(self, instance):
for id, widget in instance.parent.ids.items():
if widget.__self__ == instance:
return id
def build(self):
Builder.load_string(kv_file)
return KVMyHBoxLayout()
if __name__ == "__main__":
app = ExampleApp()
app.run()
Output:
Edit:
If you define the widget (button) in the .py file you do not need to pass the instance to the function, it is passed automatically as argument:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
class FirstScreen(Screen):
def __init__(self,**kwargs):
super(FirstScreen, self).__init__(**kwargs)
layout=BoxLayout(orientation="vertical",size_hint_y= None)
layout.bind(minimum_height=layout.setter('height'))
for i in range(50):
btn = Button(text="Button"+str(i),
id=str(i),
size_hint=(None, None),
on_press=self.Press_auth) #<<<<<<<<<<<<<<<<
layout.add_widget(btn)
root = ScrollView()
root.add_widget(layout)
self.add_widget(root)
def Press_auth(self,instance):
print(str(instance))
class TestScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(TestScreenManager, self).__init__(**kwargs)
self.add_widget(FirstScreen())
class ExampleApp(App):
def build(self):
return TestScreenManager()
def main():
app = ExampleApp()
app.run()
if __name__ == '__main__':
main()
You can use a callback function something along these lines. In your KV file:
ToggleButton:
text: 'Label'
id: halftimebutton
on_state: root.callback(self)
And then in your .py file you can do this:
def callback_halftime_state(self, instance):
if instance.state == 'down':
self.halftime == True
else:
self.halftime == False
This is of course showing the instance.state - but it could be any attribute of the button that Kivy exposes; instance.text, instance.id, etc.
example to get button text on button click :
class MainApp(MDApp):
def build(self):
VB = BoxLayout(orientation='vertical', padding=50,spacing="10")
Atbtn = Button(text="AT (Automata Theory)", font_size="25sp")
Atbtn.bind(on_press=self.callback)
Pybtn = Button(text="Python", font_size="25sp")
Pybtn.bind(on_press=self.callback)
VB.add_widget(Atbtn)
VB.add_widget(Pybtn)
return VB
def callback(self, instance):
print(instance.text)

Categories

Resources