Search code examples
python-2.7kivykivy-language

Python : Close popup using enter key


How to dismiss popup.dismiss() using enter key. when i run test.py after click on ok button then open a popup.
Can someone tell me how to close popup using enter key and after close popup set focus=True into name TextInput.

test.py

import kivy

kivy.require('1.9.0')  # replace with your current kivy version !
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout

Window.size = (500, 150)


class TestScreen(Screen):

    def insert_data(self):
        Alert(title='yeah!', text='inputs are invalid')

class Alert(Popup):

    def __init__(self, title, text):
        super(Alert, self).__init__()

        box = BoxLayout(orientation='vertical', padding=(5))
        box.add_widget(Label(text=text))
        btn1 = Button(text="Close")
        box.add_widget(btn1)

        popup = Popup(title=title, title_size=(30),
                      title_align='center', content=box,
                      size_hint=(None, None), size=(300, 200),
                      auto_dismiss=True)

        btn1.bind(on_press=popup.dismiss)
        popup.open()


class Test(App):
    def build(self):
        self.root = Builder.load_file('test.kv')
        return self.root



if __name__ == '__main__':
    Test().run()

test.kv

TestScreen:

    GridLayout:
        cols: 2
        padding: 30, 30
        spacing: 10, 10
        row_default_height: '30dp'

        Label:
            text: 'Name'
            text_size: self.size
            valign: 'middle'
            #padding_x: 50

        TextInput:
            id: name

        Button:
            text: 'Ok'
            on_press: root.insert_data()

        Button:
            text: 'Cancel'
            on_press: app.stop()

Solution

  • In the example below, the following steps were done:

    1. Use Keyboard interface that is returned by WindowBase.request_keyboard() to detect ENTER or NUMPENTERPAD key pressed.
    2. Use an ObjectProperty to hook up to the TextInput.
    3. Set auto_dismiss to False so that we invoke dismiss_callback method to give focus to TextInput (id: name) when the popup dismiss.
    4. Class Alert is already a Popup widget, and you don't want to create another popup.

    it is generally regarded as ‘best practice’ to use the ObjectProperty. This creates a direct reference, provides faster access and is more explicit.

    Example

    main.py

    from kivy.uix.screenmanager import Screen
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.popup import Popup
    from kivy.uix.label import Label
    from kivy.uix.button import Button
    from kivy.core.window import Window
    from kivy.uix.boxlayout import BoxLayout
    from kivy.properties import ObjectProperty
    
    Window.size = (500, 150)
    
    
    class TestScreen(Screen):
        name = ObjectProperty(None)
    
        def insert_data(self):
            Alert(title='yeah!', text='inputs are invalid')
    
    
    class Alert(Popup):
    
        def __init__(self, title, text):
            super(Alert, self).__init__()
            self._keyboard = Window.request_keyboard(
                self._keyboard_closed, self, 'text')
            if self._keyboard.widget:
                # If it exists, this widget is a VKeyboard object which you can use
                # to change the keyboard layout.
                pass
            self._keyboard.bind(on_key_down=self._on_keyboard_down)
    
            box = BoxLayout(orientation='vertical', padding=(5))
            box.add_widget(Label(text=text))
            btn1 = Button(text="Close")
            box.add_widget(btn1)
    
            self.title = title
            self.title_size = 30
            self.title_align = 'center'
            self.content = box
            self.size_hint = (None, None)
            self.size = (300, 200)
            self.auto_dismiss = False
    
            btn1.bind(on_press=self.dismiss_callback)
            self.open()
    
        def _keyboard_closed(self):
            self._keyboard.unbind(on_key_down=self._on_keyboard_down)
            self._keyboard = None
    
        def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
            if keycode[1] in ('enter', 'numpadenter'):
                print("keycode=", keycode)
                self.dismiss_callback()
    
            # Keycode is composed of an integer + a string
            # If we hit escape, release the keyboard
            if keycode[1] == 'escape':
                keyboard.release()
    
            # Return True to accept the key. Otherwise, it will be used by
            # the system.
            return True
    
        def dismiss_callback(self, instance=None):
            self.dismiss()
            App.get_running_app().root.name.focus = True
    
    
    class Test(App):
        def build(self):
            self.root = Builder.load_file('test.kv')
            return self.root
    
    
    if __name__ == '__main__':
        Test().run()
    

    Output

    Img01 - Text entered Img02 - ENTER pressed Img03 - NUMPENTERPAD pressed