ZetCode

GTK# 中的菜单

最后修改于 2023 年 10 月 18 日

在本 GTK# 编程教程中,我们将学习如何使用菜单。

一个菜单栏是 GUI 应用程序中最常见的组成部分之一。它是一组位于不同菜单中的命令。虽然在控制台应用程序中,我们必须记住各种深奥的命令,但在这里,我们的大部分命令都分组到逻辑部分中。这些是公认的标准,进一步减少了学习新应用程序所需的时间。

简单菜单

在我们的第一个例子中,我们将创建一个带有一个文件菜单的菜单栏。菜单将只有一个菜单项。通过选择该项,应用程序将退出。

simplemenu.cs
using Gtk;
using System;
 
class SharpApp : Window {
 

    public SharpApp() : base("Simple menu")
    {
        SetDefaultSize(250, 200);
        SetPosition(WindowPosition.Center);
        DeleteEvent += delegate { Application.Quit(); };
        
        MenuBar mb = new MenuBar();

        Menu filemenu = new Menu();
        MenuItem file = new MenuItem("File");
        file.Submenu = filemenu;
       
        MenuItem exit = new MenuItem("Exit");
        exit.Activated += OnActivated;
        filemenu.Append(exit);

        mb.Append(file);

        VBox vbox = new VBox(false, 2);
        vbox.PackStart(mb, false, false, 0);

        Add(vbox);

        ShowAll();
    }

    void OnActivated(object sender, EventArgs args)
    {
        Application.Quit();
    }

    public static void Main()
    {
        Application.Init();
        new SharpApp();
        Application.Run();
    }
}

这是一个具有最小菜单栏功能的小例子。

MenuBar mb = new MenuBar();

MenuBar 控件被创建。

Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;

顶级 MenuItem 被创建。

MenuItem exit = new MenuItem("Exit");
exit.Activated += OnActivated;
filemenu.Append(exit);

退出 MenuItem 被创建并附加到文件 MenuItem

mb.Append(file);

顶级 MenuItem 被附加到 MenuBar 控件。

VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);

与其他工具包不同,我们必须自己处理布局管理。我们将菜单栏放入垂直框中。

Simple menu
图:简单菜单

图片菜单

在下一个例子中,我们将进一步探索菜单。我们为菜单项添加图片和快捷键。快捷键是用于激活菜单项的键盘快捷键。

imagemenu.cs
using Gtk;
using System;
 
class SharpApp : Window {
 

    public SharpApp() : base("Image menu")
    {
        SetDefaultSize(250, 200);
        SetPosition(WindowPosition.Center);
        DeleteEvent += delegate { Application.Quit(); };
        
        MenuBar mb = new MenuBar();

        Menu filemenu = new Menu();
        MenuItem file = new MenuItem("File");
        file.Submenu = filemenu;
       
        AccelGroup agr = new AccelGroup();
        AddAccelGroup(agr);

        ImageMenuItem newi = new ImageMenuItem(Stock.New, agr);
        newi.AddAccelerator("activate", agr, new AccelKey(
            Gdk.Key.n, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
        filemenu.Append(newi);

        ImageMenuItem open = new ImageMenuItem(Stock.Open, agr);
        open.AddAccelerator("activate", agr, new AccelKey(
            Gdk.Key.n, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
        filemenu.Append(open);

        SeparatorMenuItem sep = new SeparatorMenuItem();
        filemenu.Append(sep);

        ImageMenuItem exit = new ImageMenuItem(Stock.Quit, agr);
        exit.AddAccelerator("activate", agr, new AccelKey(
            Gdk.Key.q, Gdk.ModifierType.ControlMask, AccelFlags.Visible));

        exit.Activated += OnActivated;
        filemenu.Append(exit);

        mb.Append(file);

        VBox vbox = new VBox(false, 2);
        vbox.PackStart(mb, false, false, 0);
        vbox.PackStart(new Label(), false, false, 0);

        Add(vbox);

        ShowAll();
    }

    void OnActivated(object sender, EventArgs args)
    {
        Application.Quit();
    }


    public static void Main()
    {
        Application.Init();
        new SharpApp();
        Application.Run();
    }
}

我们的例子展示了一个顶级菜单项,其中包含三个子级菜单项。每个菜单项都有一个图片和一个快捷键。退出菜单项的快捷键是有效的。

AccelGroup agr = new AccelGroup();
AddAccelGroup(agr);

为了使用快捷键,我们创建一个全局 AccelGroup 对象。它将在稍后使用。

ImageMenuItem newi = new ImageMenuItem(Stock.New, agr);

ImageMenuItem 被创建。图像来自图像库。

exit.AddAccelerator("activate", agr, new AccelKey(
    Gdk.Key.q, Gdk.ModifierType.ControlMask, AccelFlags.Visible));

这为退出菜单项创建了一个 Ctrl+Q 快捷键。

SeparatorMenuItem sep = new SeparatorMenuItem();
filemenu.Append(sep);

这些行创建一个分隔符。它用于将菜单项分组为逻辑组。

Image menu
图:图片菜单

CheckMenuItem

一个 CheckMenuItem 是一个带有复选框的菜单项。它可用于处理布尔属性。

checkmenuitem.cs
using Gtk;
using System;
 
class SharpApp : Window {
 
    private Statusbar statusbar;

    public SharpApp() : base("Check menu item")
    {
        SetDefaultSize(250, 200);
        SetPosition(WindowPosition.Center);
        DeleteEvent += delegate { Application.Quit(); };
        
        MenuBar mb = new MenuBar();

        Menu filemenu = new Menu();
        MenuItem file = new MenuItem("File");
        file.Submenu = filemenu;

        Menu viewmenu = new Menu();
        MenuItem view = new MenuItem("View");
        view.Submenu = viewmenu;

        CheckMenuItem stat = new CheckMenuItem("View Statusbar");
        stat.Toggle();
        stat.Toggled += OnStatusView;
        viewmenu.Append(stat);
       
        MenuItem exit = new MenuItem("Exit");
        exit.Activated += OnActivated;
        filemenu.Append(exit);

        mb.Append(file);
        mb.Append(view);

        statusbar = new Statusbar();
        statusbar.Push(1, "Ready");

        VBox vbox = new VBox(false, 2);
        vbox.PackStart(mb, false, false, 0);
        vbox.PackStart(new Label(), true, false, 0);
        vbox.PackStart(statusbar, false, false, 0);

        Add(vbox);

        ShowAll();
    }

    void OnStatusView(object sender, EventArgs args)
    {
        CheckMenuItem item = (CheckMenuItem) sender;

        if (item.Active) {
            statusbar.Show();
        } else {
            statusbar.Hide();
        }
    }
 
    void OnActivated(object sender, EventArgs args)
    {
        Application.Quit();
    }

    public static void Main()
    {
        Application.Init();
        new SharpApp();
        Application.Run();
    }
}

在我们的代码示例中,我们展示了一个复选菜单项。如果复选框被激活,则显示状态栏控件。如果不是,则隐藏状态栏。

CheckMenuItem stat = new CheckMenuItem("View Statusbar");

CheckMenuItem 控件被创建。

stat.Toggle();

Toggle 方法检查/取消选中复选菜单项。

if (item.Active) {
    statusbar.Show();
} else {
    statusbar.Hide();
}

根据 CheckMenuItem 的状态,我们显示或隐藏状态栏控件。

CheckMenuItem
图:CheckMenuItem

子菜单

我们的最后一个例子演示了如何在 GTK# 中创建子菜单。

submenu.cs
using Gtk;
using System;
 
class SharpApp : Window {
 

    public SharpApp() : base("Submenu")
    {
        SetDefaultSize(250, 200);
        SetPosition(WindowPosition.Center);
        DeleteEvent += delegate { Application.Quit(); };
        
        MenuBar mb = new MenuBar();

        Menu filemenu = new Menu();
        MenuItem file = new MenuItem("File");
        file.Submenu = filemenu;

        // submenu creation
        Menu imenu = new Menu();

        MenuItem import = new MenuItem("Import");
        import.Submenu = imenu;

        MenuItem inews = new MenuItem("Import news feed...");
        MenuItem ibookmarks = new MenuItem("Import bookmarks...");
        MenuItem imail = new MenuItem("Import mail...");

        imenu.Append(inews);
        imenu.Append(ibookmarks);
        imenu.Append(imail);

        // exit menu item
        MenuItem exit = new MenuItem("Exit");
        exit.Activated += OnActivated;
       
        filemenu.Append(import);
        filemenu.Append(exit);
        mb.Append(file);

        VBox vbox = new VBox(false, 2);
        vbox.PackStart(mb, false, false, 0);
        vbox.PackStart(new Label(), false, false, 0);

        Add(vbox);

        ShowAll();
    }

    void OnActivated(object sender, EventArgs args)
    {
        Application.Quit();
    }

    public static void Main()
    {
        Application.Init();
        new SharpApp();
        Application.Run();
    }
}

子菜单创建。

Menu imenu = new Menu();

子菜单是一个 Menu

MenuItem import = new MenuItem("Import");
import.Submenu = imenu;

它是属于顶级文件菜单的菜单项的子菜单。

MenuItem inews = new MenuItem("Import news feed...");
MenuItem ibookmarks = new MenuItem("Import bookmarks...");
MenuItem imail = new MenuItem("Import mail...");

imenu.Append(inews);
imenu.Append(ibookmarks);
imenu.Append(imail);

子菜单有自己的菜单项。

Submenu
图:子菜单

在本 GTK# 编程库的这一章中,我们展示了如何使用菜单。