-
-
Notifications
You must be signed in to change notification settings - Fork 149
Open
Labels
Description
One more bug I'm running into with some more interactive menus:
Environment information
- OS: Ubuntu 25.10
- python version: v3.13.7
- pygame version: v2.6.1
- pygame-menu version: v4.5.2
Describe the bug
With two inter-dependent drop menus I'm unable to have a satisfying solution that allows selecting an item from drop menu with both keyboard and mouse.
Stand-alone code to Reproduce The Bug
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import pygame
import pygame_menu
USE_ONRETURN = False # initial mode
CARS = [
("Ford", "Ford"),
("Toyota", "Toyota"),
("Tesla", "Tesla"),
]
ENGINES_BY_CAR = {
"Ford": [
("V6", "v6"),
("V8", "v8"),
("EcoBoost", "ecoboost"),
],
"Toyota": [
("Inline-4", "i4"),
("Hybrid", "hybrid"),
("V6", "v6"),
],
"Tesla": [
("Single Motor", "single"),
("Dual Motor", "dual"),
("Plaid", "plaid"),
],
}
def build_menu(surface, app_state):
theme = pygame_menu.themes.THEME_DARK.copy()
menu = pygame_menu.Menu(
title = "Title",
width = surface.get_width(),
height = surface.get_height(),
theme = theme
)
state = {"engine_ds": None}
def on_car_change(selected_value, _widget):
car = selected_value[0][1]
engines = ENGINES_BY_CAR.get(car, [])
if not engines:
engines = [("— No engines —", None)]
state["engine_ds"].update_items(engines)
state["engine_ds"].show()
state["engine_ds"].reset_value()
menu.render()
def on_engine_change(selected_value, _widget):
pass
def change_mode():
app_state["use_onreturn"] = not app_state["use_onreturn"]
app_state["rerender"] = True
menu.disable() # return from mainloop so we can rebuild
def quit_app():
app_state["running"] = False
app_state["rerender"] = False
menu.disable()
use_onreturn = app_state["use_onreturn"]
menu.add.label("Select a car, then an engine.")
menu.add.vertical_margin(10)
if use_onreturn:
menu.add.label("Car drop-select mode: onreturn (keyboard works; Mouse select won't update Engine drop-menu).")
else:
menu.add.label("Car drop-select mode: onchange (mouse works; Enter+arrows selects car immediately).")
menu.add.vertical_margin(20)
kwargs = dict(
selection_box_height = 5,
selection_infinite = True,
placeholder = "Select…",
default = 0
)
if use_onreturn:
menu.add.dropselect(
title = "Car: ",
items = CARS,
onreturn = on_car_change,
**kwargs
)
else:
menu.add.dropselect(
title = "Car: ",
items = CARS,
onchange = on_car_change,
**kwargs
)
engine_ds = menu.add.dropselect(
title = "Engine: ",
items = [("Select a car first", None)],
onchange = on_engine_change,
**kwargs
)
engine_ds.hide()
state["engine_ds"] = engine_ds
menu.add.vertical_margin(20)
menu.add.button("Change Mode", change_mode)
menu.add.button("Quit", quit_app)
return menu
def main() -> None:
pygame.init()
surface = pygame.display.set_mode((1600, 900))
pygame.display.set_caption("DropSelect PoC: Car → Engine")
app_state = {
"use_onreturn": USE_ONRETURN,
"rerender": False,
"running": True,
}
while app_state["running"]:
app_state["rerender"] = False
menu = build_menu(surface, app_state)
menu.mainloop(surface)
if not app_state["rerender"]:
break
pygame.quit()
sys.exit()
if __name__ == "__main__":
try:
main()
except SystemExit:
pygame.quit()
sys.exit()
Expected behavior
Selecting with mouse and keyboard should feel intuitive. My hunch says the bug boils down to this:
Currently: Hovering cursor over opened drop menu items: ignored, clicking on item: onchange event
Should be: Hovering cursor over opened drop menu items: onchange event, clicking on item: onreturn event