界面设计习练后,下面写一些程序设计心得。
程序结构
先看一下程序总体结构,先在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是图中的样子,像个黑盒子接线箱,编程时连通相应的信号即可。
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使用方法在下篇心得中写。