pyapp-kit / magicgui

build GUIs from type annotations
https://pyapp-kit.github.io/magicgui/
MIT License
361 stars 49 forks source link

Keyword argument to specify that hitting <enter> executes widget. #673

Open gatoniel opened 6 hours ago

gatoniel commented 6 hours ago

Hi, I wanted my widget to execute when I hit instead of clicking on the Run button with my mouse. Asking ChatGPT, I solved the problem with the following code:

from magicgui import magicgui
from qtpy.QtWidgets import QLineEdit, QPushButton

@magicgui(call_button="Execute")
def my_widget(input: int = 0) -> int:
    # This is where you define your plugin's functionality
    print(f"Executed with input: {input}")
    return input + 1

# Get access to the underlying QWidget
widget = my_widget.native

# Find the input field and button from the widget
input_field = widget.findChild(QLineEdit)
execute_button = widget.findChild(QPushButton)

# Save the original keyPressEvent to call it later
original_key_press_event = input_field.keyPressEvent

# Define a new keyPressEvent handler
def on_key_press(event):
    if event.key() == 16777220:  # Qt.Key_Enter or Qt.Key_Return
        execute_button.click()  # Trigger button click on Enter
    else:
        # Call the original keyPressEvent for other keys (letters, numbers, etc.)
        original_key_press_event(event)

# Connect the keyPressEvent to the input field
input_field.keyPressEvent = on_key_press

# Add the widget to napari viewer (you must have napari viewer running)
viewer = napari.Viewer()
viewer.window.add_dock_widget(my_widget)
napari.run()

This works. But it seems overly complicated. Is there a way to accomplish the same by just setting a correct keyword argument? If not, can this be integrated as new feature?

Best, Niklas

tlambert03 commented 6 hours ago

hey @gatoniel, magicgui doesn't currently deal with customization of keybindings, so it would indeed be a feature request. (and your current solution of using the underlying .native widget's API is indeed the only solution ... whether GPT gave you the most elegant approach for that is perhaps another question, but I don't think it's too far off).

Particularly in the context of napari, i think this is a feature that would require a good degree of consideration (since napari also manages keybindings for you, and it could get annoying to have to reconcile two different keybinding registries). If I were you, I would either stick with the solution of modifying the native widget, or, if your use case is strictly in napari, see if you can use napari's API for custom keyboard shortcuts