I've been having issues with ModalView that opens after one of the button is pressed within the dropdown menu.
I need to find a way to detect somehow whether the button with the id "yes" that is within that MyPopup class in my Kivy file was pressed or not, because I need it to trigger a function in the screen class. For the purpose of this question I just named it function_to_trigger()
I didn't include the full code that I have within that screen class as first of all, it would be too long (my question is long enough without I think) and secondly, the only issue that I have is with this MyPopup class that is within my Kivy file.
ACTUAL RESULT:
function_to_trigger()
is NOT triggered when the "YES" button in the ModalView is pressed. It doesn't work as expected.EXPECTED RESULT:
function_to_trigger()
is triggered ONLY IF the "YES" button in the ModalView is pressed or if the user is redirected to the main_menu screen..py file:
from kivy.uix.screenmanager import Screen
from kivymd.uix.menu.menu import MDDropdownMenu
from kivy.factory import Factory
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class SomeScreen(Screen):
def function_to_trigger(self):
print('I was triggered by yes button in the ModalView!')
def dropdown(self):
menu_list = [
{
"viewclass": "OneLineListItem",
"text" : "SOUND ON",
"theme_text_color": "Custom",
"on_release": lambda x="SOUND ON": self.sound_off(menu_list[1]["text"]),
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
},
{
"viewclass": "OneLineListItem",
"text": "RETURN TO MAIN MENU",
"on_release": lambda x="RETURN TO MAIN MENU": [Factory.get('MyPopup')().open(), menu.dismiss()],
"theme_text_color": "Custom",
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
}
]
menu = MDDropdownMenu(
caller=self.ids.burger_menu,
items=menu_list,
width_mult=4.2,
background_color=[0,0,0,1],
radius=10
)
menu.open()
## By the way the function below doesn't work and I also need to find a way how to fix this, but this is a topic for another question I think.
def sound_off(self, text_item):
if text_item == "SOUND ON":
text_item = "SOUND OFF"
return text_item
else:
text_item = "SOUND ON"
return text_item
class HamburgerButton(Button):
pass
class ExitButton(Button, HoverBehavior):
background = ListProperty((120/255, 120/255, 120/255, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (120/255, 120/255, 120/255, 1)
self.color = (1, 1, 1, 1)
.kv file:
<SomeScreen>
name: "some_screen"
FloatLayout:
orientation: 'horizontal'
size: 1280, 720
HamburgerButton:
id: burger_menu
on_release: root.dropdown()
<HamburgerButton>
size : 95, 95
size_hint: None, None
pos_hint: {'center_x': .205, 'center_y': .19}
background_normal: 'burger_menu.png'
<ExitButton>
background_color: 0, 0, 0, 0
background_normal: ''
font_name: 'Roboto'
font_size: 18
bold: True
canvas.before:
Color:
rgba: self.background
RoundedRectangle:
size: self.size
pos: self.pos
radius: [20]
<MyPopup@ModalView>
size_hint: None, None
background_color: 0, 0, 0, 1
size: 450, 250
auto_dismiss: False
canvas.before:
Color:
rgba: root.background_color
RoundedRectangle:
pos: self.pos
size: self.size
radius: [20,]
BoxLayout:
orientation: "vertical"
Label:
text: "ARE YOU SURE YOU WANT TO EXIT?"
font_name: 'Roboto'
font_size: 20
bold: True
BoxLayout:
size_hint_y: 0.3
ExitButton:
id: yes
text: "YES"
on_release:
app.root.current = "main_menu"
root.dismiss()
ExitButton:
text: "NO"
bold: True
on_release: root.dismiss()
Burger Menu Icon:
What I tried to resolve this issue:
1. Creating a MyPopup class within the file with SomeScreen and referring it in the Kivy file under on_release parameter of "yes" button. It didn't work.
.py file:
from kivy.uix.screenmanager import Screen
from kivymd.uix.menu.menu import MDDropdownMenu
from kivy.factory import Factory
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class SomeScreen(Screen):
def function_to_trigger(self):
print('I was triggered by yes button in the ModalView!')
def dropdown(self):
menu_list = [
{
"viewclass": "OneLineListItem",
"text" : "SOUND ON",
"theme_text_color": "Custom",
"on_release": lambda x="SOUND ON": self.sound_off(menu_list[1]["text"]),
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
},
{
"viewclass": "OneLineListItem",
"text": "RETURN TO MAIN MENU",
"on_release": lambda x="RETURN TO MAIN MENU": [Factory.get('MyPopup')().open(), menu.dismiss()],
"theme_text_color": "Custom",
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
}
]
menu = MDDropdownMenu(
caller=self.ids.burger_menu,
items=menu_list,
width_mult=4.2,
background_color=[0,0,0,1],
radius=10
)
menu.open()
# By the way the function below doesn't work and I also need to find a way how to fix this, but this is a topic for another question I think.
def sound_off(self, text_item):
if text_item == "SOUND ON":
text_item = "SOUND OFF"
return text_item
else:
text_item = "SOUND ON"
return text_item
class HamburgerButton(Button):
pass
class ExitButton(Button, HoverBehavior):
background = ListProperty((120/255, 120/255, 120/255, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (120/255, 120/255, 120/255, 1)
self.color = (1, 1, 1, 1)
class MyPopup(ModalView):
def trigger_function(self):
screen = SomeScreen()
screen.function_to_trigger()
# I also tried the following but it didn't work either.
def trigger_function(self):
if self.ids.yes.on_release is True:
SomeScreen.function_to_trigger(SomeScreen())
.kv file:
<MyPopup@ModalView>
size_hint: None, None
background_color: 0, 0, 0, 1
size: 450, 250
auto_dismiss: False
canvas.before:
Color:
rgba: root.background_color
RoundedRectangle:
pos: self.pos
size: self.size
radius: [20,]
BoxLayout:
orientation: "vertical"
Label:
text: "ARE YOU SURE YOU WANT TO EXIT?"
font_name: 'Roboto'
font_size: 20
bold: True
BoxLayout:
size_hint_y: 0.3
ExitButton:
id: yes
text: "YES"
on_release:
app.root.current = "main_menu"
root.trigger_function()
root.dismiss()
ExitButton:
text: "NO"
bold: True
on_release: root.dismiss()
2. Referencing MyPopup class with the help of Kivy Factory within the dropdown function. It didn't work as expected as the function was triggered as soon as the dropdown was opened when it should have been triggered ONLY when the YES button is pressed and the user is redirected to the main_menu screen. It didn't even take into consideration the fact that the ModalView wasn't opened at all.
.py file:
from kivy.uix.screenmanager import Screen
from kivymd.uix.menu.menu import MDDropdownMenu
from kivy.factory import Factory
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class SomeScreen(Screen):
def function_to_trigger(self):
print('I was triggered by yes button in the ModalView!')
def dropdown(self):
menu_list = [
{
"viewclass": "OneLineListItem",
"text" : "SOUND ON",
"theme_text_color": "Custom",
"on_release": lambda x="SOUND ON": self.sound_off(menu_list[1]["text"]),
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
},
{
"viewclass": "OneLineListItem",
"text": "RETURN TO MAIN MENU",
"on_release": lambda x="RETURN TO MAIN MENU": [Factory.get('MyPopup')().open(), menu.dismiss()],
"theme_text_color": "Custom",
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
}
]
menu = MDDropdownMenu(
caller=self.ids.burger_menu,
items=menu_list,
width_mult=4.2,
background_color=[0,0,0,1],
radius=10
)
menu.open()
if Factory.get('MyPopup')().ids.yes.on_release is True:
self.function_to_trigger()
# By the way the function below doesn't work and I also need to find a way how to fix this, but this is a topic for another question I think.
def sound_off(self, text_item):
if text_item == "SOUND ON":
text_item = "SOUND OFF"
return text_item
else:
text_item = "SOUND ON"
return text_item
class HamburgerButton(Button):
pass
class ExitButton(Button, HoverBehavior):
background = ListProperty((120/255, 120/255, 120/255, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (120/255, 120/255, 120/255, 1)
self.color = (1, 1, 1, 1)
3. Creating a function within the SomeScreen class that would be triggered if App.get_running_app().root_current = 'main_menu' but it didn't work and I knew it wouldn't work because if the user had already been redirected to the main_menu screen, then the SomeScreen class wouldn't have been aware of this. Anyway, it didn't work.
4. Creating a function within a ScreenManager similar to the one in point number 3. Basically, what I attempted to do was to create a function that would trigger function_to_trigger() IF the App.get_running_app().root.current == 'main_screen' but it didn't work.
5. Creating a function like the one in the point number 1, BUT within SomeScreen class. It didn't work either.
py.file
from kivy.uix.screenmanager import Screen
from kivymd.uix.menu.menu import MDDropdownMenu
from kivy.factory import Factory
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class SomeScreen(Screen):
def function_to_trigger(self):
print('I was triggered by yes button in the ModalView!')
def trigger_function(self):
if Factory.get('MyPopup')().ids.yes.on_release is True:
self.function_to_trigger()
def dropdown(self):
menu_list = [
{
"viewclass": "OneLineListItem",
"text" : "SOUND ON",
"theme_text_color": "Custom",
"on_release": lambda x="SOUND ON": self.sound_off(menu_list[1]["text"]),
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
},
{
"viewclass": "OneLineListItem",
"text": "RETURN TO MAIN MENU",
"on_release": lambda x="RETURN TO MAIN MENU": [Factory.get('MyPopup')().open(), menu.dismiss()],
"theme_text_color": "Custom",
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
}
]
menu = MDDropdownMenu(
caller=self.ids.burger_menu,
items=menu_list,
width_mult=4.2,
background_color=[0,0,0,1],
radius=10
)
menu.open()
if Factory.get('MyPopup')().ids.yes.on_release is True:
self.function_to_trigger()
# By the way the function below doesn't work and I also need to find a way how to fix this, but this is a topic for another question I think.
def sound_off(self, text_item):
if text_item == "SOUND ON":
text_item = "SOUND OFF"
return text_item
else:
text_item = "SOUND ON"
return text_item
class HamburgerButton(Button):
pass
class ExitButton(Button, HoverBehavior):
background = ListProperty((120/255, 120/255, 120/255, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (120/255, 120/255, 120/255, 1)
self.color = (1, 1, 1, 1)
EDIT
MINIMAL REPRODUCIBLE EXAMPLE:
main.py
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from windowmanager import WindowManager
class MinimalApp(MDApp):
def build(self):
Builder.load_file('minimalapp.kv')
if __name__ == '__main__':
MinimalApp().run()
windowmanager.py
from kivy.uix.screenmanager import ScreenManager
from main_menu import MainMenu
from second_screen import SecondScreen
class WindowManager(ScreenManager):
pass
main_menu.py
from kivy.uix.screenmanager import Screen
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class MainMenu(Screen):
pass
class ButtonMenu(Button, HoverBehavior):
background = ListProperty((0, 0, 0, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (0, 0, 0, 1)
self.color = (1, 1, 1, 1)
main_menu.kv
<MainMenu>:
name: 'main_menu'
FloatLayout:
orientation: 'horizontal'
size: 1280, 720
ButtonMenu:
text: 'GO TO SOME SCREEN'
pos_hint: {'center_x': .5, 'center_y': .42}
on_release:
app.root.current = "second_screen"
root.manager.transition.direction = "left"
<ButtonMenu>
background_color: 0, 0, 0, 0
background_normal: ''
size_hint: 0.5, 0.11
font_size: 32
font_name: 'Roboto'
bold: True
canvas.before:
Color:
rgba: self.background
RoundedRectangle:
size: self.size
pos: self.pos
radius: [28]
Color:
rgba: (0, 0, 0, 1) # separate color for line border
Line:
rounded_rectangle: (self.pos[0], self.pos[1], self.size[0], self.size[1], 28)
width: 2
minimalapp.kv
#: include main_menu.kv
#: include second_screen.kv
WindowManager:
MainMenu:
SecondScreen:
second_screen.py
from kivy.uix.screenmanager import Screen
from kivymd.uix.menu.menu import MDDropdownMenu
from kivy.factory import Factory
from kivy.uix.modalview import ModalView
from kivymd.uix.behaviors.hover_behavior import HoverBehavior
from kivy.uix.button import Button
from kivy.properties import ListProperty
class SecondScreen(Screen):
def function_to_trigger(self):
print('I was triggered by yes button in the ModalView!')
def dropdown(self):
menu_list = [
{
"viewclass": "OneLineListItem",
"text": "SOUND ON",
"theme_text_color": "Custom",
"on_release": lambda x="SOUND ON": self.sound_off(menu_list[1]["text"]),
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
},
{
"viewclass": "OneLineListItem",
"text": "RETURN TO MAIN MENU",
"on_release": lambda x="RETURN TO MAIN MENU": [Factory.get('MyPopup')().open(), menu.dismiss()],
"theme_text_color": "Custom",
"text_color": [1, 1, 1, 1],
"text_style": "BUTTON",
"font_style": "H6"
}
]
menu = MDDropdownMenu(
caller=self.ids.burger_menu,
items=menu_list,
width_mult=4.2,
background_color=[0, 0, 0, 1],
radius=10
)
menu.open()
## By the way the function below doesn't work and I also need to find a way how to fix this, but this is a topic for another question I think.
def sound_off(self, text_item):
if text_item == "SOUND ON":
text_item = "SOUND OFF"
return text_item
else:
text_item = "SOUND ON"
return text_item
class HamburgerButton(Button):
pass
class ExitButton(Button, HoverBehavior):
background = ListProperty((120/255, 120/255, 120/255, 1))
color = ListProperty((1, 1, 1, 1))
def on_enter(self):
self.background = (1, 222/255, 89/255, 1)
self.color = (0, 0, 0, 1)
def on_leave(self):
self.background = (120/255, 120/255, 120/255, 1)
self.color = (1, 1, 1, 1)
second_screen.kv
<SecondScreen>
name: 'second_screen'
FloatLayout:
orientation: 'horizontal'
size: 1280, 720
HamburgerButton:
id: burger_menu
on_release: root.dropdown()
<HamburgerButton>
size : 95, 95
size_hint: None, None
pos_hint: {'center_x': .205, 'center_y': .19}
background_normal: 'burger_menu.png'
<ExitButton>
background_color: 0, 0, 0, 0
background_normal: ''
font_name: 'Roboto'
font_size: 18
bold: True
canvas.before:
Color:
rgba: self.background
RoundedRectangle:
size: self.size
pos: self.pos
radius: [20]
<MyPopup@ModalView>
size_hint: None, None
background_color: 0, 0, 0, 1
size: 450, 250
auto_dismiss: False
canvas.before:
Color:
rgba: root.background_color
RoundedRectangle:
pos: self.pos
size: self.size
radius: [20,]
BoxLayout:
orientation: "vertical"
Label:
text: "ARE YOU SURE YOU WANT TO EXIT?"
font_name: 'Roboto'
font_size: 20
bold: True
BoxLayout:
size_hint_y: 0.3
ExitButton:
id: yes
text: "YES"
on_release:
app.root.current = "main_menu"
root.dismiss()
ExitButton:
text: "NO"
bold: True
on_release: root.dismiss()
Try adding:
app.root.get_screen('second_screen').function_to_trigger()
to the on_release:
of the YES
button.