Gio.Menu 项始终禁用布尔操作
Gio.Menu items always disabled for boolean actions
我似乎无法使 GMenu 项适用于布尔状态操作。
这是一个 MCVE(灵感来自 LiuLang’s example 如何使用 GMenu 和 GAction):
#!/usr/bin/env python3
# Copyright (C) 2013 LiuLang <gsushzhsosgsu@gmail.com>
# Use of this source code is governed by GPLv3 license that can be found
# in http://www.gnu.org/licenses/gpl-3.0.html
from gi.repository import Gio, Gtk, GLib
import sys
menus_str ='''
<?xml version="1.0"?>
<interface>
<menu id="menubar">
<submenu id="appmenu">
<attribute name="label" translatable="yes">App</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Toggle broken</attribute>
<attribute name="action">app.toggle</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Radios select A</attribute>
<attribute name="action">app.radio</attribute>
<attribute name="target">A</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Radios select B</attribute>
<attribute name="action">app.radio</attribute>
<attribute name="target">B</attribute>
</item>
</section>
</submenu>
</menu>
</interface>
'''
class App:
def __init__(self):
self.app = Gtk.Application.new('org.liulang.test', 0)
self.app.connect('startup', self.on_app_startup)
self.app.connect('activate', self.on_app_activate)
def run(self, argv):
self.app.run(argv)
def on_app_activate(self, app):
self.window.show_all()
def on_app_startup(self, app):
self.window = Gtk.ApplicationWindow.new(app)
self.window.set_default_size(640, 480)
self.window.set_title('Gio Actions Demo')
self.window.set_border_width(5)
app.add_window(self.window)
builder = Gtk.Builder()
# It is better to load ui from a seperate file
builder.add_from_string(menus_str)
builder.connect_signals(self)
menubar = builder.get_object('menubar')
app.set_menubar(menubar)
# No-state no-parameter action 'quit'
action = Gio.SimpleAction.new('quit', None)
action.connect('activate', lambda *args: self.app.quit())
self.app.add_action(action)
# Boolean state action 'toggle' − should display as a checkbox ?
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), GLib.Variant('b', True))
action.connect('activate', lambda action, target: print('toggling boolean action to', target.get_boolean()) or action.change_state(target))
self.app.add_action(action)
# String state action 'radio' − correctly displays as a radio
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), GLib.Variant('b', True))
action = Gio.SimpleAction.new_stateful('radio', GLib.VariantType.new('s'), GLib.Variant('s', 'A'))
action.connect('activate', lambda action, target: print('toggling radio action to', target.get_string()) or action.change_state(target))
self.app.add_action(action)
if __name__ == '__main__':
app = App()
app.run(sys.argv)
我希望菜单中的第二项是反映 toggled
操作状态的复选框。相反,我得到的项目始终显示为灰色,即使操作处于活动状态也是如此。
菜单项似乎与操作紧密相连,因为它的完成方式与其他有效操作相同,并且使用 Gtk.Application.set_accels_for_action
添加快捷方式会在菜单中显示加速器。交互式调试(使用 GTK_DEBUG=interactive
)确认操作处于活动状态。
请看下面的菜单截图:
我似乎无法弄清楚我做错了什么。文档很少,只包含简单的无状态操作示例。 google 这个问题也很难解决,因为 Gtk 有 3 种或 4 种不同的菜单和操作范例以及诸如此类的东西,这会扰乱任何搜索尝试。
我在 some source code 中找到了以下评论:
* ## Boolean State
*
* An action with a boolean state will most typically be used with a "toggle"
* or "switch" menu item. The state can be set directly, but activating the
* action (with no parameter) results in the state being toggled.
*
* Selecting a toggle menu item will activate the action. The menu item should
* be rendered as "checked" when the state is true.
但是 GMenuModel wiki documentation 中列出的属性似乎都不允许 select 切换项目。这也不是其他操作的工作方式,请参阅从未指定样式的单选示例。
事实证明,布尔可切换动作不带参数,动作中包含的状态就足够了。
即代码必须是:
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), None)
我似乎无法使 GMenu 项适用于布尔状态操作。
这是一个 MCVE(灵感来自 LiuLang’s example 如何使用 GMenu 和 GAction):
#!/usr/bin/env python3
# Copyright (C) 2013 LiuLang <gsushzhsosgsu@gmail.com>
# Use of this source code is governed by GPLv3 license that can be found
# in http://www.gnu.org/licenses/gpl-3.0.html
from gi.repository import Gio, Gtk, GLib
import sys
menus_str ='''
<?xml version="1.0"?>
<interface>
<menu id="menubar">
<submenu id="appmenu">
<attribute name="label" translatable="yes">App</attribute>
<section>
<item>
<attribute name="label" translatable="yes">Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Toggle broken</attribute>
<attribute name="action">app.toggle</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Radios select A</attribute>
<attribute name="action">app.radio</attribute>
<attribute name="target">A</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Radios select B</attribute>
<attribute name="action">app.radio</attribute>
<attribute name="target">B</attribute>
</item>
</section>
</submenu>
</menu>
</interface>
'''
class App:
def __init__(self):
self.app = Gtk.Application.new('org.liulang.test', 0)
self.app.connect('startup', self.on_app_startup)
self.app.connect('activate', self.on_app_activate)
def run(self, argv):
self.app.run(argv)
def on_app_activate(self, app):
self.window.show_all()
def on_app_startup(self, app):
self.window = Gtk.ApplicationWindow.new(app)
self.window.set_default_size(640, 480)
self.window.set_title('Gio Actions Demo')
self.window.set_border_width(5)
app.add_window(self.window)
builder = Gtk.Builder()
# It is better to load ui from a seperate file
builder.add_from_string(menus_str)
builder.connect_signals(self)
menubar = builder.get_object('menubar')
app.set_menubar(menubar)
# No-state no-parameter action 'quit'
action = Gio.SimpleAction.new('quit', None)
action.connect('activate', lambda *args: self.app.quit())
self.app.add_action(action)
# Boolean state action 'toggle' − should display as a checkbox ?
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), GLib.Variant('b', True))
action.connect('activate', lambda action, target: print('toggling boolean action to', target.get_boolean()) or action.change_state(target))
self.app.add_action(action)
# String state action 'radio' − correctly displays as a radio
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), GLib.Variant('b', True))
action = Gio.SimpleAction.new_stateful('radio', GLib.VariantType.new('s'), GLib.Variant('s', 'A'))
action.connect('activate', lambda action, target: print('toggling radio action to', target.get_string()) or action.change_state(target))
self.app.add_action(action)
if __name__ == '__main__':
app = App()
app.run(sys.argv)
我希望菜单中的第二项是反映 toggled
操作状态的复选框。相反,我得到的项目始终显示为灰色,即使操作处于活动状态也是如此。
菜单项似乎与操作紧密相连,因为它的完成方式与其他有效操作相同,并且使用 Gtk.Application.set_accels_for_action
添加快捷方式会在菜单中显示加速器。交互式调试(使用 GTK_DEBUG=interactive
)确认操作处于活动状态。
请看下面的菜单截图:
我似乎无法弄清楚我做错了什么。文档很少,只包含简单的无状态操作示例。 google 这个问题也很难解决,因为 Gtk 有 3 种或 4 种不同的菜单和操作范例以及诸如此类的东西,这会扰乱任何搜索尝试。
我在 some source code 中找到了以下评论:
* ## Boolean State
*
* An action with a boolean state will most typically be used with a "toggle"
* or "switch" menu item. The state can be set directly, but activating the
* action (with no parameter) results in the state being toggled.
*
* Selecting a toggle menu item will activate the action. The menu item should
* be rendered as "checked" when the state is true.
但是 GMenuModel wiki documentation 中列出的属性似乎都不允许 select 切换项目。这也不是其他操作的工作方式,请参阅从未指定样式的单选示例。
事实证明,布尔可切换动作不带参数,动作中包含的状态就足够了。
即代码必须是:
action = Gio.SimpleAction.new_stateful('toggle', GLib.VariantType.new('b'), None)