如何用一些 GtkMenuItem 填充 GtkMenu 并在 Glade 中设置其父项?
How to populate a GtkMenu with some GtkMenuItem and set its parent in Glade?
在 Gtk.Toolbar
中,我有一个 Gtk.MenuToolButton
和一个箭头,我想将其关联到一个 Gtk.Menu
,最好是在 Glade 中的 built。
我的代码是这样的:
self.menuToolButtonCalculate.set_menu(self.get_object("menuCalculate"))
其中self.menuToolButtonCalculate
是通过Gtk.Builder.get_object
方法得到的,self是Gtk.Builder
.
的子类实例
程序在 window 加载时在终端中显示了一些 Gtk/Gdk-CRITICAL
警告,当我单击箭头时程序崩溃了。在显示 window 之前,我还在 Python 代码中填充了 Glade 中定义的 Gtk.Menu
,但程序仍然崩溃,所以我现在确定问题不在于菜单是空的。
为了测试目的,我用这个替换了那行:
self.menuToolButtonCalculate.set_menu(Gtk.Menu())
程序在加载 window 时仍会在终端中显示 Gtk/Gdk-CRITICAL
警告,但是当我单击箭头时程序不会崩溃,它会在箭头附近显示一个空的上下文菜单。
这些 Gtk/Gdk-CRITICAL
警告是:
(python2.exe:14672): Gtk-CRITICAL **: gtk_widget_set_size_request: assertion 'GTK_IS_WIDGET (widget)' failed
(python2.exe:14672): Gtk-CRITICAL **: gtk_container_add: assertion 'GTK_IS_CONTAINER (container)' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_window_get_height: assertion 'GDK_IS_WINDOW (window)' failed
(python2.exe:14672): Gtk-CRITICAL **: gtk_widget_reparent: assertion 'priv->parent != NULL' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_window_get_width: assertion 'GDK_IS_WINDOW (window)' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_device_get_position_double: assertion 'GDK_IS_DEVICE (device)' failed
我使用安装了最新更新的 Windows 10 Pro x64,安装了最新更新的 MSYS2,以及 MSYS2 内部的 x86 版本:Python 2.7.13、Glade 3.20 和 GTK+ 3.22。
更新:
奇怪的是,在终端中没有崩溃或警告的情况下完美运行的简化测试代码:
example1.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="menuToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">__glade_unnamed_2</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
example1.py
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
b = Gtk.Builder()
b.add_from_file("example1.glade")
w = b.get_object("window1")
mtb = b.get_object("menuToolButton")
m = b.get_object("menu")
mtb.set_menu(m)
w.connect("delete-event", Gtk.main_quit)
w.show_all()
Gtk.main()
原程序太大,这里放不下。请告诉我您希望我了解原始代码的哪些细节 post 以便您可以帮助我。
更新 2:
在主程序的 Glade .ui 文件中,我对 GtkMenu 的定义如下:
<object class="GtkMenu" id="menuCalculate">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tearoff_state">True</property>
<property name="tearoff_title">Ce dorești să calculez?</property>
</object>
如果我删除最后两个元素(导致程序行为发生变化的是tearoff_state
)
<object class="GtkMenu" id="menuCalculate">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
当我单击 Glade 文件中声明的 GtkMenuToolButton
、GtkMenu
的箭头时,程序没有崩溃,它打开了一个空菜单。
所以问题是由在 Glade 中创建的 GtkMenu
引起的,它没有父级并且被 tearoff_state
属性 请求 uired。
- 如果这是真的,将
GtkMenu
的父级设置为 GtkMenuToolButton
(箭头)的推荐方法是什么,最好是在 Glade 中,但至少在代码中?
- 据我所知,不可能用 Glade 中的项目填充
GtkMenu
,因此我必须从代码中填充它。这是真的吗?
可以将 GtkMenu
分配给 Glade 中的 GtkMenuToolButton
,菜单内容也可以
填充 GtkMenu
已将 GtkMenu 添加到您的 Glade 项目 select 它在侧边栏中,您应该会看到一个额外的工具栏图标出现:
这将打开菜单编辑器:
从这里您可以切换到 'Hierarchy' 选项卡,您可以在其中使用 + / - 按钮添加从菜单中删除的项目
将 GtkMenu 分配给 GtkMentToolButton
现在不幸的是 Glade 不支持这样做但是底层的 GtkBuilder 文件格式支持 as explained in the docs
GtkMenuToolButton as GtkBuildable
The GtkMenuToolButton implementation of the GtkBuildable interface supports adding a menu by specifying “menu” as the “type” attribute of a element.
An example for a UI definition fragment with menus:
<object class="GtkMenuToolButton">
<child type="menu">
<object class="GtkMenu"/>
</child>
</object>
所以点击保存(并退出)并切换到像 Gedit 这样的文本编辑器,我希望你的文件看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Yes</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">You Can</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Define Menus</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">In Glade</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</interface>
现在在 GtkMenuToolButton
中创建一个 <child type="menu">
,如下所示:
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
<child type="menu">
</child>
</object>
然后在 <child type="menu">
中剪切并粘贴 GtkMenu
定义,不用担心缩进 Glade 接下来会解决这个问题。
文件现在应该如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
<child type="menu">
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Yes</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">You Can</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Define Menus</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">In Glade</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
现在保存并关闭文件,然后在 Glade 中再次打开它。
您现在应该看到 glade 将其识别为 'menu child',点击保存,Glade 也会为您整理缩进
在 Windows 10
上使用 Glade 3.20.0
在 Gtk.Toolbar
中,我有一个 Gtk.MenuToolButton
和一个箭头,我想将其关联到一个 Gtk.Menu
,最好是在 Glade 中的 built。
我的代码是这样的:
self.menuToolButtonCalculate.set_menu(self.get_object("menuCalculate"))
其中self.menuToolButtonCalculate
是通过Gtk.Builder.get_object
方法得到的,self是Gtk.Builder
.
程序在 window 加载时在终端中显示了一些 Gtk/Gdk-CRITICAL
警告,当我单击箭头时程序崩溃了。在显示 window 之前,我还在 Python 代码中填充了 Glade 中定义的 Gtk.Menu
,但程序仍然崩溃,所以我现在确定问题不在于菜单是空的。
为了测试目的,我用这个替换了那行:
self.menuToolButtonCalculate.set_menu(Gtk.Menu())
程序在加载 window 时仍会在终端中显示 Gtk/Gdk-CRITICAL
警告,但是当我单击箭头时程序不会崩溃,它会在箭头附近显示一个空的上下文菜单。
这些 Gtk/Gdk-CRITICAL
警告是:
(python2.exe:14672): Gtk-CRITICAL **: gtk_widget_set_size_request: assertion 'GTK_IS_WIDGET (widget)' failed
(python2.exe:14672): Gtk-CRITICAL **: gtk_container_add: assertion 'GTK_IS_CONTAINER (container)' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_window_get_height: assertion 'GDK_IS_WINDOW (window)' failed
(python2.exe:14672): Gtk-CRITICAL **: gtk_widget_reparent: assertion 'priv->parent != NULL' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_window_get_width: assertion 'GDK_IS_WINDOW (window)' failed
(python2.exe:14672): Gdk-CRITICAL **: gdk_device_get_position_double: assertion 'GDK_IS_DEVICE (device)' failed
我使用安装了最新更新的 Windows 10 Pro x64,安装了最新更新的 MSYS2,以及 MSYS2 内部的 x86 版本:Python 2.7.13、Glade 3.20 和 GTK+ 3.22。
更新:
奇怪的是,在终端中没有崩溃或警告的情况下完美运行的简化测试代码:
example1.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="menuToolButton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">__glade_unnamed_2</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
example1.py
# coding=utf-8
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
b = Gtk.Builder()
b.add_from_file("example1.glade")
w = b.get_object("window1")
mtb = b.get_object("menuToolButton")
m = b.get_object("menu")
mtb.set_menu(m)
w.connect("delete-event", Gtk.main_quit)
w.show_all()
Gtk.main()
原程序太大,这里放不下。请告诉我您希望我了解原始代码的哪些细节 post 以便您可以帮助我。
更新 2:
在主程序的 Glade .ui 文件中,我对 GtkMenu 的定义如下:
<object class="GtkMenu" id="menuCalculate">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tearoff_state">True</property>
<property name="tearoff_title">Ce dorești să calculez?</property>
</object>
如果我删除最后两个元素(导致程序行为发生变化的是tearoff_state
)
<object class="GtkMenu" id="menuCalculate">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
当我单击 Glade 文件中声明的 GtkMenuToolButton
、GtkMenu
的箭头时,程序没有崩溃,它打开了一个空菜单。
所以问题是由在 Glade 中创建的 GtkMenu
引起的,它没有父级并且被 tearoff_state
属性 请求 uired。
- 如果这是真的,将
GtkMenu
的父级设置为GtkMenuToolButton
(箭头)的推荐方法是什么,最好是在 Glade 中,但至少在代码中? - 据我所知,不可能用 Glade 中的项目填充
GtkMenu
,因此我必须从代码中填充它。这是真的吗?
可以将 GtkMenu
分配给 Glade 中的 GtkMenuToolButton
,菜单内容也可以
填充 GtkMenu
已将 GtkMenu 添加到您的 Glade 项目 select 它在侧边栏中,您应该会看到一个额外的工具栏图标出现:
这将打开菜单编辑器:
从这里您可以切换到 'Hierarchy' 选项卡,您可以在其中使用 + / - 按钮添加从菜单中删除的项目
将 GtkMenu 分配给 GtkMentToolButton
现在不幸的是 Glade 不支持这样做但是底层的 GtkBuilder 文件格式支持 as explained in the docs
GtkMenuToolButton as GtkBuildable
The GtkMenuToolButton implementation of the GtkBuildable interface supports adding a menu by specifying “menu” as the “type” attribute of a element.
An example for a UI definition fragment with menus:
<object class="GtkMenuToolButton">
<child type="menu">
<object class="GtkMenu"/>
</child>
</object>
所以点击保存(并退出)并切换到像 Gedit 这样的文本编辑器,我希望你的文件看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Yes</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">You Can</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Define Menus</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">In Glade</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</interface>
现在在 GtkMenuToolButton
中创建一个 <child type="menu">
,如下所示:
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
<child type="menu">
</child>
</object>
然后在 <child type="menu">
中剪切并粘贴 GtkMenu
定义,不用担心缩进 Glade 接下来会解决这个问题。
文件现在应该如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuToolButton" id="toolbutton">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Menu</property>
<property name="use_underline">True</property>
<child type="menu">
<object class="GtkMenu" id="menu">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Yes</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">You Can</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Define Menus</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">In Glade</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</interface>
现在保存并关闭文件,然后在 Glade 中再次打开它。
您现在应该看到 glade 将其识别为 'menu child',点击保存,Glade 也会为您整理缩进
在 Windows 10
上使用 Glade 3.20.0