.NET Core 跨平台 GUI 開發之 GTtkSharp 初級篇


.NET Core 跨平台 GUI 開發之 GTtkSharp 初級篇

GTK 來龍去脈

  1. Linux 上的圖形界面可有可無,有需要的話是可以安裝的,作為一個軟件安裝到系統。比如常見的桌面環境有 KDE 和 GNOME,它們不僅是個窗口管理器,還提供了桌面、菜單等功能,。桌面管理器顧名思義了,沒有它的話就不能打開多個窗口不能最大最小化沒有邊框等,所以希望整個系統只跑一個桌面程序的情況就可以不用安裝窗口管理器。windows 用戶按 https://zhidao.baidu.com/question/1372025356510156779.html 這個操作可以體驗一下,請先好保存當前工作再操作
  2. KDE 和 GNOME 分別基於 Qt 和 Gtk 實現。它們通過一種叫 X11 的協議來通信,不僅控制窗口最大最小化縮放和邊框,還提供桌面、工具狀態欄等
  3. X11 可用於幾乎所有已有的現代操作系統,基於客戶端——服務器模型。跟常規理解不一樣,此處從應用程序視角看:本地主機 X 顯示程序提供顯示服務,遠端應用使用了該顯示服務,所謂它是客戶端。就像遠程控制桌面一樣,本地提供顯示,遠程服務器作為客戶端。當它們都在同一主機,看起來就是一個整體。比如蘋果電腦,X 協議集成在系統內核,所以性能好很多
  4. 層次關系:linux 本身-->X 服務器<--通過 X 協議交談-->窗口管理器-->X 應用程序。X 服務實現有 Xfree86、Xorg、Xnest 等,KDE 和 GNOME 屬於 X 客戶端。我們開發的桌面程序屬於 X 客戶端
  5. 為了方便開發人員,將 X 協議封裝,於是有了 XLib。類似於 windows 上的 關於通信功能的 ws2_32.dll,提供了訪問系統功能的 api,比如監聽端口和從系統緩沖區讀取端口接收的數據。很多常用功能為了方便使用,於是有了 C 函數庫 GLib,類似於 C#里面的 System 空間的很多函數,包括字符串處理、list 數據結構等。接着是 Gdk,結合 GLib,將 XLib 函數庫封裝得更友好,比如 C#中將 ws2_32.dll 一些功能封裝成 UdpClient。再往上就是 Gtk 了,依賴於 Gdk,提供基礎的工具包和 widget,是上層 GUI 派生的基礎。類似於 NewLife 的 X 組件里面的 ApiClient 這種網絡庫,基於 UdpClient 等封裝。Gtk 獲得了面向對象特性和可擴展性之后,就是 Gtk+,翻譯成 CSharp 就是 GtkSharp。類似於 X 組件,提供了很多功能和工具,提供給各個應用系統做業務。層次關系:x 協議-->XLib,GLib-->Gdk-->Gtk+

界面布局

  • Gtk#有被稱為容器對象的東西,用於指導窗口或其他容器內的布局和放置。此技術不同於使用 System.Windows.Forms 工具箱定位的常用方法。GTK#和 System.Windows.Forms 之間的主要區別在於:使用 GTK#的應用程序不使用絕對坐標或固定坐標來定位窗口小部件。使用 GTK 工具包的應用程序通過布局和包裝容器對象為其接口創建正確的布局
  • 目前,最常用的就是水平和垂直包裝盒,即 HBox 和 VBox

Box

  • 對齊控件的首選方法。優點:與屏幕尺寸無關、更容易國際化
  • 水平盒子(HBox)和垂直(VBox)盒子,對於 VBox,PackStart 將從頂部開始包裝盒子,PackEnd 將從底部開始包裝盒子。對於 HBox,PackStart 將從左到右打包盒子,PackEnd 將從右到左打包盒子。
  • 使用如下,child 參數是要打包到框中的對象。expand 參數控制框是否填充分配給它的區域(true),否則縮小框使其恰好合適框中對象大小。fill 參數控制對象是否填滿框,僅當 expand 為 true 時生效。比如日志文本框,縮放的時候,文本框跟隨窗口大小變化
box1.PackStart(Widget child, bool expand, bool fill, int padding);
  • 創建函數如下,homogeneous 表示框中的每個對象是否具有相同的大小(即,HBox 中的寬度相同或 vBox 中的高度相同),等效於 Pack 方法中 expand 為 true。spacing 表示框中對象間距,而 padding 會在對象兩側都添加
HBox hbox1 = new HBox(bool homogeneous, int  spacing);

Table

  • 除了使用 HBox 和 VBox 進行打包外,還可以使用 Table 對象進行打包。這個有點像 html 的 table,適合方方正正大小差不多的空間集合,比如計算器。
  • Table 的聲明如下,rows、columns 分別指要創建的行和列。homogeneous 為 true 表示所有的表框大小設置為大小最大那個控件,為 false 則各行和列的大小根據各行列中大小最大那個控件決定
Table table1 = new Table(int rows, int columns, bool homogeneous);

// 假如創建2*2的表格
 0          1          2
0+----------+----------+
 |          |          |
1+----------+----------+
 |          |          |
2+----------+----------+
  • 添加控件方式如下,leftAttach,rightAttach,topAttach,bottomAttachach 分別代表表中控件的左右上下邊所在位置。例如,希望某個控件占據第一行兩個格子,那么 leftAttach=0,rightAttach=2,topAttach=0,bottomAttachach=1。
  • xOptions 和 yOptions 指定打包選項
    • Gtk.AttachOptions.Fill:如果表框大於窗口小部件,並且指定了 Fill,則窗口小部件將展開以使用所有可用空間
    • Gtk.AttachOptions.Shrink:如果為 Table 中控件分配了較少的空間,然后又請求了空間(通常是由用戶調整窗口大小),則通常將窗口小部件推離窗口底部並消失。如果指定了 Shrink ,則小部件將隨表格收縮
    • Gtk.AttachOptions.Expand:這將導致 Table 擴展以占用窗口中的所有剩余空間
  • xPadding 和 yPadding 分別控制 Table 內控件在原位置基礎上表框到控件的左右或者上下距離
table1.Attach (        Widget            child,
                       int               leftAttach,
                       int               rightAttach,
                       int               topAttach,
                       int               bottomAttach,
                       Gtk.AttachOptions xOptions,
                       Gtk.AttachOptions yOptions,
                       int               xPadding,
                       int               yPadding );

其它布局

  • 固定容器 fixed,容器內控件相對於窗口左上角位置,並且位置可動態修改
Fixed fixed1 = new Fixed();
fixed1.Put(widget, x, y);
fixed1.Move(widget, x, y);
  • 布局容器 layout,實現了無限的滾動區域,適合動態加載很多空間的情況,比如相冊
Layout layout1 = new Layout(hadjustment, vadjustment);
layout1.Put(widget, x, y);
layout1.Move(widget, x, y);
  • 框架 frame,類似於 winform 的 groupbox,框上有個標簽。LabelXalign 和 LabelYalign 屬性分別表示 Label 在框上的水平和垂直位置,范圍是 0-1。LabelXalign 默認 0,標簽位於左邊,LabelYalign 未使用。ShadowType 屬性決定外框樣式 Gtk.Shadow.EtchedIn 為默認值
Frame frame1 = new Frame("Label");
frame1.LabelXalign = 0.3;
frame1.ShadowType = ShadowType.Out;

響應式編程

  • 本節介紹多線程 GTK#編程以及如何保持 GTK#應用程序的響應速度
  • 和 winform 一樣,更新 UI 應該由創建 UI 的線程來執行,否則可能會崩潰。可用 Gtk.Application.Invoke 來請求 GUI 線程完成更新
using Gtk;

class Demo {
  static Label label;

  static void Main ()
  {
    Application.Init ();
    Window w = new Window ("Cray on a Window");
    label = new Label ("Busy computing");

    Thread thr = new Thread (new ThreadStart (ThreadRoutine));
    thr.Start ();
    Application.Run ();
  }

  static void ThreadRoutine ()
  {
        LargeComputation ();
        Gtk.Application.Invoke (delegate {
              label.Text = "Done";
        });
  }

  static void LargeComputation ()
  {
    // lots of processing here
  }
}
  • 定時器 GLib.Timeout,類似 System.Windows.Forms.Timer。不同之處在於,GLib.Timeout 總是在擁有 Gtk 主循環的線程上被調用
 void StartClock ()
     {
         // 每秒調用一次update_status

         GLib.Timeout.Add (1000, new GLib.TimeoutHandler (update_status));
     }

     bool update_status ()
     {
         time_label.Text = DateTime.Now.ToString ();

         // 返回true則在下一次超時時間到達后再次調用update_status
         // 返回false則終止定時器

         return true;
     }

最后

  • 本文介紹了 Gtk 在整個 Linux 桌面開發所處位置、列舉了幾個布局容器、以及響應式編程。掌握以上知識,可大大提高編程效率,全部操作一遍即可理解並掌握


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM