Search code examples
python-3.xfocusubuntu-18.04gtk3ubuntu-20.04

Remove focus from TextEntry


I have Python3/GTK3 application with a (preferences) Dialog containing a Notebook with multiple Pages (tabs). On some of the Pages are TextEntrys along with other Widgets.

When I click into a TextEntry on one Page then switch to another Page which also contains a TextEntry, any text in the (new Page) TextEntry is highlighted. If I accidentally hit the space bar, I'll wipe out that text. To undo, I have to cancel (close) the dialog. This is unacceptable if the user has made changes in other parts of the dialog as those changes are now lost.

A representative sample script is below. I have commented out various calls to grab the focus which I have tried, but none work. I am using the Box for layout, yet in my application I use a Grid and the problem persists, so I suspect the layout container is not a culprit.

#!/usr/bin/env python3


import gi
gi.require_version( "Gtk", "3.0" )
from gi.repository import Gtk


def addPageToNotebook( notebook, text ):
    box = Gtk.Box()

    box.pack_start( Gtk.Label.new( "Label " + text ), False, False, 0 )

    textEntry = Gtk.Entry()
    textEntry.set_text( text )
    # textEntry.set_receives_default( False )
    box.pack_start( textEntry, True, True, 0 )

    button = Gtk.Button.new_with_label( "Button" + text )
    # button.set_receives_default( True )
    box.pack_start( button, False, False, 0 )

    notebook.append_page( box, Gtk.Label.new( "Tab " + text ) )
    return textEntry, button


def onSwitchPage( notebook, page, pageNumber, textEntry1, button1, textEntry2, button2 ):
    # button1.grab_focus()
    # button2.grab_focus()
    # textEntry1.grab_focus_without_selecting()
    # textEntry2.grab_focus_without_selecting()
    # notebook.get_tab_label( page ).grab_focus()
    pass


notebook = Gtk.Notebook()
textEntry1, button1 = addPageToNotebook( notebook, "1" )
textEntry2, button2 = addPageToNotebook( notebook, "2" )
notebook.connect( "switch-page", onSwitchPage, textEntry1, button1, textEntry2, button2 )

window = Gtk.Window()
window.connect( "destroy", Gtk.main_quit )
window.add( notebook )
window.show_all()
Gtk.main()

There are other posts about this situation yet nobody seems to have found a solution:

Anyone with ideas please?

Edit: Have logged an issue with GNOME.


Solution

  • I have come up with an alternate solution, based on the comment to use a thread to change the TextEntry. In summary, when the tab/page is switched, I give focus to the tab.

    #!/usr/bin/env python3
    
    
    import gi
    gi.require_version( "Gtk", "3.0" )
    from gi.repository import GLib, Gtk
    
    
    def addPageToNotebook( notebook, text ):
        box = Gtk.Box()
    
        box.pack_start( Gtk.Label.new( "Label " + text ), False, False, 0 )
    
        textEntry = Gtk.Entry()
        textEntry.set_text( text )
        box.pack_start( textEntry, True, True, 0 )
    
        button = Gtk.Button.new_with_label( "Button" + text )
        box.pack_start( button, False, False, 0 )
    
        notebook.append_page( box, Gtk.Label.new( "Tab " + text ) )
        return textEntry, button
    
    
    def setFocusOnTab( notebook, pageNumber ):
    #    notebook.get_tab_label( notebook.get_nth_page( pageNumber ) ).get_parent().grab_focus() # This is overkill...instead should be
        notebook.grab_focus()
        return False
    
    
    def onSwitchPage( notebook, page, pageNumber ):
        GLib.idle_add( setFocusOnTab, notebook, pageNumber )
    
    
    notebook = Gtk.Notebook()
    textEntry1, button1 = addPageToNotebook( notebook, "1" )
    textEntry2, button2 = addPageToNotebook( notebook, "2" )
    notebook.connect( "switch-page", onSwitchPage )
    
    window = Gtk.Window()
    window.add( notebook )
    window.show_all()
    window.connect( "destroy", Gtk.main_quit )
    Gtk.main()