我有Python3/GTK3应用程序,其中包含一个(preferences)对话框,其中包含一个具有多个页面(选项卡)的笔记本。在一些页面上有TextEntrys和其他Widgets。
当我点击一个页面上的TextEntry,然后切换到另一个也包含TextEntry的页面时,(新页面)TextEntry中的任何文本都会突出显示。如果我不小心按了空格键,我就会删掉那些文字。要撤消,我必须取消(关闭)对话框。如果用户在对话框的其他部分做了更改,这是不可接受的,因为这些更改现在会丢失。
下面是一个代表性的示例脚本。我已经注释掉了各种调用来抓住我尝试过的焦点,但没有一个工作。我使用Box进行布局,但在我的应用程序中我使用Grid,问题仍然存在,所以我怀疑布局容器不是罪魁祸首。#!/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()
也有其他关于这种情况的帖子,但似乎没有人找到解决方案:
- GTK:如何从元素开始移除焦点 如何从pygtk中删除高亮显示?
- Python Gtk 3.0:如何在笔记本中抓取焦点
- 当我点击一个小部件时,我如何在GTK中取消对所有其他小部件的聚焦?
- GTK焦点链
- Python gtk笔记本焦点链
有人有什么想法吗?
编辑:已经记录了GNOME的一个问题。
如果您想从条目中移除焦点,您应该使用grab_remove()
而不是grab_focus()
。在你的例子中:
def onSwitchPage( notebook, page, pageNumber, textEntry1, button1, textEntry2, button2 ):
# button1.grab_focus()
# button2.grab_focus()
textEntry1.grab_remove()
textEntry2.grab_remove()
# notebook.get_tab_label( page ).grab_focus()
pass
编辑:
你是对的,上面的方法也不起作用。似乎应该有一种方法来删除焦点,或防止Gtk.Entry
在第一个地方抓住它,但你可能需要子类和大量编辑它。似乎次佳的选择就是直接"标签"。焦点离开入口。为此,您必须创建一个KEY_PRESS
事件,并手动触发它。
def onSwitchPage( notebook, page, pageNumber, textEntry1, button1, textEntry2, button2 ):
focus_widget = notebook.get_toplevel().get_focus()
if focus_widget in [textEntry1, textEntry2, button1, button2]:
display = Gdk.Display().get_default()
seat = display.get_default_seat()
keyboard = seat.get_keyboard()
keymap = Gdk.Keymap().get_for_display(display)
key = keymap.get_entries_for_keyval(Gdk.KEY_Tab)
event = Gdk.Event().new(Gdk.EventType.KEY_PRESS)
event.hardware_keycode = key[1][0].keycode
event.window = notebook.get_window()
event.set_device(keyboard)
#Everything commented out isn't necessary for the event to work on my end.
# event.keyval = Gdk.KEY_Tab
# event.time = Gdk.CURRENT_TIME
# event.send_event = True
# event.type = Gdk.EventType.KEY_PRESS
# event.length = 0
# event.is_modifier = 0
# event.state = 0
# event.string = ""
# event.group = key[1][0].group
#Do it twice so focus doesn't land on button either.
for i in range(2):
display.put_event(event)
#Tried to get rid of the highlight but this didn't help.
# textEntry1.select_region(0, 0)
# textEntry2.select_region(0, 0)
EDIT2:
不幸的是,这仍然使条目文本突出显示,但没关系,事件仍然有效。也给我以下警告:
Gdk-WARNING **: Event with type 8 not holding a GdkDevice. It is most likely synthesized outside Gdk/GTK+
你提供的这个链接https://discourse.gnome.org/t/generating-gdk-gtk-keyboard-events-programmatically/11020帮助我摆脱了上面的警告。很明显,您必须在事件上使用set_device()
。
我提出了另一种解决方案,基于使用线程更改TextEntry的注释。总而言之,当标签/页面被切换时,我将焦点放在标签上。
#!/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()