Search code examples
pythondialogkeypressgtk3

Gtk.Dialog keypress as OK in Python


I have a login dialog, which works fine, but as response_ok it accepts only OK button (though as CANCEL I can press esc from keyboard). I try to make it react on ENTER key, what I thought should be very easy, but not for me. I tried with set_default_response and some others but it doesn't work. I hope there is easier way then connecting signals. Here is the code:

def get_user_pw(self):
    dialogWindow = Gtk.MessageDialog(self,Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.QUESTION,Gtk.ButtonsType.OK_CANCEL,"Log in")
    dialogBox = dialogWindow.get_content_area()
    login = Gtk.Entry()
    pas = Gtk.Entry()
    pas.set_visibility(False)
    pas.set_invisible_char("*")
    dialogBox.pack_end(has, False, False, 0)
    dialogBox.pack_end(uzytkownik, False, False, 0)
    dialogWindow.show_all()
    Gtk.Dialog.set_default_response(dialogWindow,response_id=Gtk.ResponseType.OK)
    response = dialogWindow.run()
    {some action here}
    dialogWindow.destroy()

Solution

  • I exactly had the same issue a few days ago, it turns out that the solution is using listeners on the activate signal of an Entry.

    So I edited your code such that hitting Enter in the username field moves the focus to the password field where hitting Enter emulates a click on OK.

    def get_user_pw(self):
        # Create the dialog window
        self.dialogWindow = Gtk.MessageDialog(self,Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.QUESTION,Gtk.ButtonsType.OK_CANCEL,"Log in")
    
        # Get the content area
        dialogBox = self.dialogWindow.get_content_area()
    
        # Create fields
        login = Gtk.Entry()
        pas = Gtk.Entry()
        pas.set_visibility(False)
        pas.set_invisible_char("*")
    
        # Add the fields to the dialog
        dialogBox.pack_end(pas, False, False, 0)
        dialogBox.pack_end(login, False, False, 0)
    
        # Connect activate to the username field to move to the password field when enter is hit
        login.__next_field = pas
        login.connect("activate", self.next_field)
    
        # Connect activate to submit the data when enter is hit
        pas.connect("activate", self.submit)
    
        self.dialogWindow.show_all()
    
        response = self.dialogWindow.run()
        self.dialogWindow.destroy()
    
    def submit(self, entry):
        # Send the OK response to the dialog
        self.dialogWindow.response(Gtk.ResponseType.OK)
    
    def next_field(self, entry):
        # Move the focus to the next field
        if entry.__next_field is not None:
            entry.__next_field.grab_focus()