界面设计习练后,下面写一些程序设计心得。

程序结构

先看一下程序总体结构,先在program.cs中找到main入口,在命名空间下是MainClass类,Main函数进入后首先建立应用程序环境 Application.Init,然后对MainWindow进行实例化,显示窗体并运行程序 Application.Run()。

//Program.cs

using System;
using Gtk;

namespace csharp3
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Application.Init();
            MainWindow win = new MainWindow();
            win.Show();
            Application.Run();
        }
    }
}

main -> application init -> mainwindow{builder} ->application run/quit

上述过程中,mainwindow如下,它通过gtk库产生一个窗体及窗体包含的其它widgets,然后连通widgets的信号 - 属性和事件。这其中用到一个 Build() 函数,在C调用中常命名为 builder的指针,在gnome-builder构建器中称之为 template ,将界面设计器的设计文件变成程序来实现。public partial class MainWindow, 指明这只是 partial,一部分内容,还有一部分由 Build() 产生。在linux中,Gtk界面库与用户程序之间一般都是这种方式。

//mainwindow.cs

using System;
using Gtk;

public partial class MainWindow : Gtk.Window
{
    public MainWindow() : base(Gtk.WindowType.Toplevel)
    {
        Build();
    }

    protected void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        Application.Quit();
        a.RetVal = true;
    }

    protected void OnButton5Clicked(object sender, EventArgs e)
    {
        entry2.Text = "Hello!";
    }

    protected void OnButton6Clicked(object sender, EventArgs e)
    {
        Application.Quit();
    }
}

也可以不用设计器,自己写build的内容。Mono的设计器支持C#,但不支持VB.NET,而Mono本身是支持VB.NET的。因此,如果在Mono上用VB.NET开发的话,需要自己写build后的界面语句。大至是下面的样子。首先产生个Window,然后向window中加入控件并显示控件,如果需要产生事件则将事件与回调函数过程的地址连起来(Addressof),最后show的是window。除了主窗体给个初始尺寸,控件本身一般都是由sizer,比如vbox等去控制的。习惯于linux界面这种方式后,可以不用界面设计器,脑子想它是什么样就add上什么widget,个别属性调整一下,fill和expand用好,加控件时pack靠start或靠end,最后试运行调整一下就可以了。

        Dim window As Gtk.Window = New Gtk.Window("Buttons")
        AddHandler window.DeleteEvent, AddressOf OnDeleteEvent
        window.BorderWidth = 0

        window.Resize(800, 600)
        window.WindowPosition = WindowPosition.Center

        Dim box1 As VBox = New VBox(False, 10)
        window.Add(box1)
        box1.Show()
        box1.Homogeneous = False

        Dim box2 As VBox = New VBox(False, 10)
        box2.BorderWidth = 10
        box1.PackStart(box2, True, True, 0)
        box2.Show()

        button1 = New Button("Button 1")
        box2.PackStart(button1, True, True, 0)
        button1.Show()
        AddHandler button1.Clicked, AddressOf OnButton1Clicked

        Dim button2 As Button = New Button("Button 2")
        'button2.Active = true
        box2.PackStart(button2, True, True, 0)
        button2.Show()

        Dim separator As HSeparator = New HSeparator()
        box1.PackStart(separator, False, True, 0)
        separator.Show()

        Dim box3 As VBox = New VBox(False, 10)
        box3.BorderWidth = 10
        box1.PackStart(box3, False, True, 0)

        Dim button3 As Button = New Button("Close")
        AddHandler button3.Clicked, AddressOf OnExitButtonEvent

        Dim entry1 As Entry = new Entry("Please")
        box3.PackStart(entry1, True, True, 0)
        entry1.Show()
        
        box3.PackStart(button3, True, True, 0)
        button3.CanDefault = True
        button3.GrabDefault()
        button3.Show()

Mono C#编程中,可以不关注Build后的内容,它们在另外一个.cs中。如果抽象一些理解的话,builder是图中的样子,像个黑盒子接线箱,编程时连通相应的信号即可。

Ubuntu20.4 Mono C# gtk 编程习练笔记(二)-LMLPHP

C#有设计器还是比VB.NET方便一些,不过在C#中也可以使用VB.NET功能,在引用中加上:

using VB = Microsoft.VisualBasic

引用后即产生新的命名空间VB,比如在C#中使用VB.NET的文件读写,可以写成:

                VB.FileSystem.FileOpen(1, "VBNETTEST.TXT", VB.OpenMode.Output, VB.OpenAccess.Write, VB.OpenShare.Shared);
                VB.FileSystem.WriteLine(1, "Hello World! - 1");
                VB.FileSystem.WriteLine(1, "Hello World! - 2");
                VB.FileSystem.WriteLine(1, "Hello World! - 3");
                VB.FileSystem.WriteLine(1, "Hello World! - 4");
                VB.FileSystem.WriteLine(1, "Hello World! - 5");
                VB.FileSystem.FileClose(1);

微软的Microsoft.VisualBasic命名空间中VB.NET功能繁多,喜欢VB.NET编程的话可以把它引用到进程序中,Mono的C#设计器也就间接地支持VB.NET语言开发了。

用户程序

默认的MainWindow.cs产生MainWindow:Gtk.Window类,里面有个MainWindow()方法,方法中首先是Build(),自己的程序一般使用这个类,加入一些类内变量,在类内加入一些方法等。需要的话也可另僻空间,用另类,用另类方法等。

//MainWindow.cs

using System;
using Gtk;
using System.Threading.Tasks;
using VB = Microsoft.VisualBasic;
using Cairo;

public partial class MainWindow : Gtk.Window
{
    //Store previous background color of drawingarea1
    private Gdk.Color StoreColor = new Gdk.Color(255, 255, 255);
    private int iArea1ObjX = 10;
    private int iArea1ObjY = 50;
    private uint timerID1, timerID2;
    private ImageSurface surfacepub;
    private Context ctxpub;
    private Context ctxArea1;
    private int drawingarea1Width;
    private int drawingarea1Height;


    public MainWindow() : base(Gtk.WindowType.Toplevel)
    {
        Build();

        drawingarea1.AppPaintable = true;
        CreateContext();
        timerID1 = GLib.Timeout.Add(100, OnTimedEvent1);
        timerID2 = GLib.Timeout.Add(100, OnTimedEvent2);

        /*
        aTimer = new System.Timers.Timer(300);
        aTimer.Elapsed += OnTimedEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
        */
    }

    protected void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        DestroyContext();
        Gtk.Application.Quit();
        a.RetVal = true;
    }

    protected void OnButton16Clicked(object sender, EventArgs e)
    {
        DestroyContext();
        Gtk.Application.Quit();
    }

    protected void OnColorbutton1ColorSet(object sender, EventArgs e)
    {
        var redcolor = colorbutton1.Color.Red;
        var greencolor = colorbutton1.Color.Green;
        var bluecolor = colorbutton1.Color.Blue;
    }

先写这么多,一些常用widgets使用方法在下篇心得中写。

01-18 14:20