除了使用 HBox 和 VBox 进行布局外,还可以使用 Table 对象进行布局。这个有点像 html 的 table,适合方方正正大小差不多的空间集合。本篇将会对 Table 布局进行讲解,利用 Table 做出一个计算器的界面并使其可以响应按钮点击并将点击的按钮内容展示在界面上。在 Windows 系统中效果如下:

源码地址: https://gitee.com/coderbusy/gtk-sharp-demo

1、准备项目

我们需要新建一个 .NET Core 控制台项目,在编写本篇博文时 .NET Core 3.1 LTS 版本已经发布了,所以大可以直接使用 .NET Core 3.1 版本。在引用完 GtkSharp  之后,新建一个名为 CalculatorView.cs 的类文件并使其从 Gtk.Window 中派生:

在 Programe.cs 文件中键入以下代码,用于启动窗体和运行程序:

2、Table 简介

Table 对象的构造函数需要 3 个参数,具体签名如下:

Table table1 = new Table(int rows, int columns, bool homogeneous);

rows、columns 分别指要创建的行和列。homogeneous 为 true 表示所有的表框大小设置为大小最大那个控件,为 false 则各行和列的大小根据各行列中大小最大那个控件决定 。

行和列的布局从0到n,其中 n 是在对 Table 的调用中指定的数字。因此,如果指定 rows = 2,columns = 2,则布局将如下所示:

 0          1          20+----------+----------+|          |          |1+----------+----------+|          |          |2+----------+----------+

注意,坐标系始于左上角。如果想把 Widgt 放入 Table 中,可以使用下面的代码:

table1.Attach (        Widget            child,int               leftAttach,int               rightAttach,int               topAttach,int               bottomAttach);

leftAttach,rightAttach,topAttach,bottomAttach 分别代表表中控件的左右上下边所在位置。这似乎和已有的 WinForm 编程经验不符,在 WinForm 下我们通过指定控件的位置来对其定位,指定其大小来决定其占用的空间。在 Gtk# 的世界中你仍可以将 WinForm 的思想带入,只不过,在指定了坐标 (x,y) 对应 (left,top) 之后,(right,bottom) 对应的值为 (x+width,y+height) 。

3、代码实现

遵循 Gtk# 开发的最佳实践,我们会在窗体关闭后进行应用程序退出操作。因为我们的 CalculatorView 直接从 Gtk.Window 派生,所以我们可以在构造函数中做这件事,同时对窗体进行一些细节上的调整,让他启动时出现在屏幕中央,并且不可以通过鼠标调整大小:

using System;using System.Collections.Generic;using System.Text;using Pango;namespace Gtk.Calculator{class CalculatorView : Window{public CalculatorView() : base("Gtk.Calculator"){//在窗体关闭时,退出应用程序this.DeleteEvent += CalculatorView_DeleteEvent;//设置窗体大小this.SetSizeRequest(300, 500);//设置窗体位置this.SetPosition(WindowPosition.Center);//去掉最大化按钮,不可以调整大小。this.Resizable = false;}private void CalculatorView_DeleteEvent(object o, DeleteEventArgs args){Application.Quit();}}}

计算器需要一个 Label 来显示结果,因为要对这个 Label 进行更新,所以我们将其定义为 CalculatorView 的字段:

private readonly Label _lblDisplay;

添加一个 DefaultMargin 属性,用来表示按钮之间的间距:

/// <summary>/// 获取或设置 按钮之间的间距/// </summary>public int DefaultMargin { get; set; } = 3;

我们需要一个 6 行 4 列的表格来进行布局,创建表格后,将其添加到视图中,然后把显示结果的 Lable 也进行初始化,添加到 Table 的第一行并占满它。该 Label 中的文字在水平方向上居右,在垂直方向上在底部:

//创建一个 6 行 4 列的表格var table = new Table(6, 4, false);this.Add(table);//创建一个标签,用来显示结果
_lblDisplay = new Label { Halign = Align.End, Margin = this.DefaultMargin, Valign = Align.End };
table.Attach(_lblDisplay, 0, 4, 0, 1);

接下来就是填充按钮了。新建一个 CreateButton 方法用于创建按钮,该方法接收一个字符串参数作为按钮上显示的文字,并注册按钮的 Clicked 方法。在按钮被 Click 后,将按钮上的文字附加到 Label 中:

private Button CreateButton(String text){var btn = new Button(text) { Margin = DefaultMargin };btn.Clicked += Btn_Clicked;return btn;}private void Btn_Clicked(object sender, EventArgs e){if (sender is Button btn){this._lblDisplay.Text += btn.Label;}}

下面就是略微烧脑的代码了,补充计算器所需的按钮。一堆参数,写起来还是需要小心翼翼:

//补充计算器的按钮//leftAttach,rightAttach,topAttach,bottomAttach 分别代表表中控件的左右上下边所在位置
table.Attach(CreateButton("AC"), 0, 1, 1, 2);
table.Attach(CreateButton("+/-"), 1, 2, 1, 2);
table.Attach(CreateButton("%"), 2, 3, 1, 2);
table.Attach(CreateButton("+"), 3, 4, 1, 2);table.Attach(CreateButton("7"), 0, 1, 2, 3);
table.Attach(CreateButton("8"), 1, 2, 2, 3);
table.Attach(CreateButton("9"), 2, 3, 2, 3);
table.Attach(CreateButton("*"), 3, 4, 2, 3);table.Attach(CreateButton("4"), 0, 1, 3, 4);
table.Attach(CreateButton("5"), 1, 2, 3, 4);
table.Attach(CreateButton("6"), 2, 3, 3, 4);
table.Attach(CreateButton("-"), 3, 4, 3, 4);table.Attach(CreateButton("1"), 0, 1, 4, 5);
table.Attach(CreateButton("2"), 1, 2, 4, 5);
table.Attach(CreateButton("3"), 2, 3, 4, 5);
table.Attach(CreateButton("+"), 3, 4, 4, 5);table.Attach(CreateButton("0"), 0, 2, 5, 6);
table.Attach(CreateButton("."), 2, 3, 5, 6);
table.Attach(CreateButton("="), 3, 4, 5, 6);

至此,我们的计算器界面就做好了。完整代码可以查看:CalculatorView.cs

关于 Table 的官方介绍,可以参看这里:GtkSharp: Packing with Tables

4、事件处理

与 WinForm 中的 Button 类似,Gtk# 中的 Button 也拥有点击事件,这点上文已经实践过。在 Gtk# 的世界中,所有从 Widget 派生的挂件均含有以下事件:

ButtonPressEventButtonReleaseEventScrollEventMotionNotifyEventDeleteEventDestroyEventExposeEventKeyPressEventKeyReleaseEventEnterNotifyEventLeaveNotifyEventConfigureEventFocusInEventFocusOutEventMapEventUnmapEventPropertyNotifyEventSelectionClearEventSelectionRequestEventSelectionNotifyEventProximityInEventProximityOutEventVisibilityNotifyEventClientEventNoExposeEventWindowStateEvent

但事实上,当我们尝试订阅 Label 的 ButtonPressEvent 时就会发现预期的事件处理器并没有被执行:

using System;namespace Gtk.EventDemo{class Program{static void Main(string[] args){Application.Init();var win = new Window("Gtk.EventDemo");win.SetDefaultSize(250, 100);win.SetPosition(WindowPosition.Center);win.DeleteEvent += (s, e) =>{Application.Quit();};var lbl = new Label("标签内容");lbl.ButtonPressEvent += (s, e) => { Console.WriteLine("标签被点击:" + e); };win.Add(lbl);win.ShowAll();Application.Run();}}}

上述代码在被运行后,即使使用鼠标点击了 Label ,因为 Label 没有关联的窗体所以对应的事件处理器不会被调用。这样的部件有许多,常见的有以下几个:

Gtk.Alignment           Gtk.Arrow          Gtk.BinGtk.Box                 Gtk.Button         Gtk.CheckButtonGtk.Fixed               Gtk.Image          Gtk.LabelGtk.MenuItem            Gtk.Notebook       Gtk.PanedGtk.RadioButton         Gtk.Range          Gtk.ScrolledWindowGtk.Separator           Gtk.Table          Gtk.ToolbarGtk.AspectFrame         Gtk.Frame          Gtk.VBoxGtk.HBox                Gtk.VSeparator     Gtk.HSeparator

即便 Label 控件无法直接响应事件,但是我们仍旧可以通过 EventBox 对象来实现捕获 Label 事件的功能。具体来说,将 EventBox 嵌套在 Label 外即可:

using System;namespace Gtk.EventDemo{class Program{static void Main(string[] args){Application.Init();var win = new Window("Gtk.EventDemo");win.SetDefaultSize(250, 100);win.SetPosition(WindowPosition.Center);win.DeleteEvent += (s, e) =>{Application.Quit();};var lbl = new Label("标签内容");var box = new EventBox();box.Add(lbl);box.ButtonPressEvent += (s, e) => { Console.WriteLine("标签被点击:" + e); };win.Add(box);win.ShowAll();Application.Run();}}}

启动程序后,可以看到点击事件被成功捕获:

【.NET Core 跨平台 GUI 开发】第三篇:Gtk# 表格布局与事件处理相关推荐

  1. 【.NET Core 跨平台 GUI 开发】第一篇:编写你的第一个 Gtk# 应用

    本文是[.NET Core 跨平台 GUI 开发]系列博文的第一篇.该系列博文是一个关于 Gtk# 跨平台应用开发的初级随笔集合.该随笔集合介绍了 GTK 和 Gtk# 的基本信息以及开发方法,并展示 ...

  2. core开发linux桌面应用,【.NET Core 跨平台 GUI 开发】第一篇:编写你的第一个 Gtk# 应用...

    本文是[.NET Core 跨平台 GUI 开发]系列博文的第一篇.该系列博文是一个关于 Gtk# 跨平台应用开发的初级随笔集合.该随笔集合介绍了 GTK 和 Gtk# 的基本信息以及开发方法,并展示 ...

  3. 【.NET Core 跨平台 GUI 开发】第二篇:Gtk# 布局入门,初识HBox 和 VBox

    这是 Gtk# 系列博文的第二篇.在上一篇博文<编写你的第一个 Gtk# 应用>中,我们提到"一个 Gtk.Window 只能直接包含一个部件".这意味着,在不做其他额 ...

  4. Agv、Rgv 车辆控制调度系统开发第三篇

    Agv.Rgv 车辆控制调度系统开发第三篇地图编辑器 Agv.Rgv 车辆控制调度系统开发第三篇地图编辑器 Agv.Rgv 车辆控制调度系统开发第三篇地图编辑器 前言 一.GOJS 二.使用步骤 1. ...

  5. 跨平台应用开发进阶(三十八)uni-app前端监控方案:基调听云APP探究

    文章目录 一.前言 二.产品介绍 2.1 工作原理 2.1.1 Android平台工作原理 2.1.2 iOS平台工作原理 三.项目集成 3.1 Android集成 3.2 iOS集成 四.答疑解惑 ...

  6. wpf 开源框架_.NET Core跨平台基础框架:10 篇热文汇总

    (给DotNet加星标,提升.Net技能) 本文精选了DotNet 2019年12月份的10篇热门文章.其中有技术分享.技术资源. 注:以下文章,点击标题即可阅读 <C#异步编程 > Ta ...

  7. 跨平台应用开发进阶(三十):uni-app 实现集成火山视频直播服务

    文章目录 一.前言 二.技术实现 2.1 web-view组件在app中的窗体关系和plus.webview操作方式 三.双向通信 3.1 uni-app与内嵌网页通信 3.2 内嵌网页向uni-ap ...

  8. Android 应用开发(38)TableLayout(表格布局)

    TableLayout(表格布局) 前面我们已经学习了平时实际开发中用得较多的线性布局(LinearLayout)与相对布局(RelativeLayout), 其实学完这两个基本就够用了,笔者在实际开 ...

  9. 跨平台应用开发进阶(三): uni-app 实现资源在线升级/热更新

    文章目录 一.前言 1.1 Android升级检测机制 二.wgt 资源升级包升级 2.1 修改版本号 2.2 发行 2.3 安装资源升级包 2.3.1 代码示例 2.3.2 小结 三.整包升级 3. ...

最新文章

  1. 配置bind主域名服务器
  2. Nginx的proxy_cache缓存功能
  3. android studio 配置国内镜像
  4. emacs mysql_使用Emacs作为MySQL的客户端
  5. ZooKeeper Web UI -- Shovel
  6. JDBC batch批处理Statement executeBatch 具体解释
  7. Jan 11 - Contains Duplicate II; Array; Traverse; HashMap; HashSet;
  8. python通用数据库连接_python-sqlalchemy 使用学习记录之基础连接数据库安装接篇...
  9. Java itext tiff转换pdf
  10. 浏览器内核的解析和对比
  11. java ts视频文件转mp4格式在线求助
  12. Timus 1104. Don’t Ask Woman about Her Age
  13. Dynamics 365 批量删除记录
  14. C语言:fscanf函数与fprintf函数——格式化读写函数
  15. 梳理:WPS JS宏之WPS表格单元格读写值
  16. RTX3060是什么级别显卡 RTX3060显卡什么水平
  17. 金蝶迷你版凭证导入工具_金蝶凭证批量导入方法
  18. 函数的闭包,闭包的用途
  19. ssm+jsp计算机毕业设计游戏装备交易网站192yb(程序+lw+源码+远程部署)
  20. CV未来,路在何方?李飞飞指路!

热门文章

  1. 降低winnt Apache服务的权限,让你的虚拟主机更安全
  2. 有意思的记录-shell(持续更新)
  3. 如何在Word,Excel和PowerPoint 2010中裁剪图片
  4. 什么是Google On.Here,以及如何设置?
  5. 可执行文件添加快捷方式_如何停止Windows向快捷方式文件名添加“-快捷方式”...
  6. plex实现流媒体服务器_如何从Plex Media Server离线查看下载和同步媒体
  7. 一维条形码***技术(Badbarcode)
  8. List 集合转换为String
  9. 关于F5 排错的简单介绍之一
  10. 莫名其妙的主机名 VM_32_234_centos