用Vala开发带菜单栏的Gtk4应用:编译正常但菜单栏不显示求助
问题:Gtk4应用菜单栏无法显示
我尝试用Vala编写一个简单的Gtk4应用,想添加一个包含两项功能的菜单栏:打印“Hello, World”和退出程序。使用命令:
valac --pkg=gtk4 menutest.vala
编译正常完成,窗口能显示,但菜单栏在macOS(通过Homebrew部署环境)和Fedora系统中都不出现。
以下是我的代码:
// menutest.vala using Gtk; public class Menutest : Gtk.Application { public Menutest() { Object (application_id: "org.gtk.menutest"); } protected override void activate() { var window = new ApplicationWindow (this); window.title = "Hello World"; // Create a menu with two items var menu = new Menu(); menu.insert(0, "Hello", "app.hello"); menu.insert(1, "Quit", "app.quit"); // Set the menu as the application's menubar this.set_menubar(menu); // Define the actions for the menu items SimpleAction hello = new SimpleAction("hello", null); hello.activate.connect(hello_action); this.add_action(hello); SimpleAction quit = new SimpleAction("quit", null); quit.activate.connect(quit_action); this.add_action(quit); window.present(); } public static int main (string[] args) { return new Menutest().run (args); } // The callback function for the "Hello" action private void hello_action (SimpleAction action, Variant? parameter) { print ("Hello, world!\n"); } // The callback function for the "Quit" action private void quit_action (SimpleAction action, Variant? parameter) { this.quit (); } }
运行效果:
- macOS系统:窗口正常显示,但屏幕顶部和窗口内均无菜单栏
- Fedora系统:窗口正常显示,但窗口内无菜单栏
请问哪里操作出错了?
解决方案
问题核心是Gtk4中Gtk.Menu已被废弃,它属于旧版菜单API,不再适用于创建应用菜单栏。你需要改用Gtk4推荐的Gio.MenuModel结合Gtk.MenuBar的方式实现。
修改后的代码如下:
// menutest.vala using Gtk; public class Menutest : Gtk.Application { public Menutest() { Object (application_id: "org.gtk.menutest"); } protected override void activate() { var window = new ApplicationWindow (this); window.title = "Hello World"; // 创建Gtk4推荐的菜单模型 var menu_model = new Gio.Menu(); menu_model.append("Hello", "app.hello"); menu_model.append("Quit", "app.quit"); // 创建菜单栏并绑定模型 var menubar = new Gtk.MenuBar(); menubar.menu_model = menu_model; // 创建垂直容器承载菜单栏(Gtk4窗口需要明确设置子组件) var main_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0); main_box.append(menubar); window.child = main_box; // 注册菜单动作 var hello_action = new SimpleAction("hello", null); hello_action.activate.connect(() => { print("Hello, world!\n"); }); add_action(hello_action); var quit_action = new SimpleAction("quit", null); quit_action.activate.connect(() => { quit(); }); add_action(quit_action); window.present(); } public static int main (string[] args) { return new Menutest().run(args); } }
补充说明:
- 在macOS上,Gtk4默认会将应用菜单合并到系统顶部菜单栏,若想强制菜单栏显示在窗口内,可添加以下代码(在
window.present()前):var settings = Gtk.Settings.get_default(); settings.set_string("gtk-decoration-layout", "menubar:"); - 编译命令保持不变,重新编译运行后,菜单栏即可正常显示。
内容的提问来源于stack exchange,提问作者AthanasiusOfAlex
相关产品推荐
相关产品推荐

