当程序员准备设计一个GUI(图形用户界面)的时候,他将面对许多特殊的问题:视觉效果、可伸缩性、可调整的性能、修改便利性等等。版面管理器通过设置版面化对象的大小和位置帮助你解决了这些问题,同时其本身也是版面化的。Java程序员对版面管理器的概念应该是比较熟悉的,但从其它编程背景中转到 C# 的程序员可能需要对此逐渐熟悉。如果你的编程背景是Java,可以直接阅读下面有关Java和C#中版面管理器的区别部分。 何为版面管理器 版面管理器能够决定版面化对象的尺寸和大小。版面管理器是可以用在任何场合的,不过它最广泛的应用还是在GUI设计中。近些年出现的一些工具(其中大多数是基于Borland的伟大的 C++ 系列)使得GUI的设计更加简单,但即使是这样,GUI设计还是一个较复杂的问题。对于那些想使这个问题简单化或是想更直接控制版面的人,版面管理器应该是一个较好的解决之道。版面管理器为程序员的设计带来了许多实在的帮助,通过使用版面管理器的嵌套和区域管理,几乎所有的配置都成为可能。另外,版面管理器还能帮助程序员解决 GUI开发中一些“令人讨厌”的部分,比如调整尺寸、正常版面、可伸缩性,让程序员能够将更多的时间集中于设计哪些更有意义的部分。 Java和 C#中版面管理器的区别 Java中的版面管理器与在C#中执行的版面管理器主要有两个区别。首先,在 Java中,版面管理器只是纯粹被用在图形用户界面的区域,即只有组件可以用版面管理器来排版。在C#的版面管理器中,所有执行ILayoutable界面的对象都可以进行排版,这样就在图形及地图设计等领域中提供了更多设计上的可能性。第二个不同与第一个有关。由于这里执行的版面管理器并不直接受GUI对象的约束,而只是编排版面化对象的抽象概念,因此就有可能将版面管理器用于母控制的独特区域。你可以在母控制中指定一个矩形区域,给它一个版面管理器,向它增加子控制。如此,我们不但拥有了哪些Java中的标准版面管理器操作外,还为GUI设计带来了难以置信的威力。 如何使用版面库 在本文中所执行的版面管理器的版面库对于原来的 Java程序员来说可能是很熟悉的,它基于两个界面:Ilayoutable和 IlayoutManager,后者是对 Ilayoutable的扩展。库的其余部分包括这两个界面对 GUI 设计的特殊问题的执行。 ControlBox :这是控件版面结构的基础,是Controls的基础包装类。 ContainerBox :从ControlBox中继承而来,能够增加其它 ControlBoxes 并布置它们。 AreaPane :从ContainerBox中继承而来,其作用相当于最高级别面板。它在一个矩形区域中布置了被添加到其中的各种控件。 ResizeablePane :从 AreaPane中继承而来,唯一的不同是它总是调整到其母控件的客户端尺寸。 库中提供的还有一些样本版面: BorderLayout :允许5个不同的版面化对象,在北、南、东、西和中央各一个。所有组件的大小都被压缩了,北和南在垂直方向上尽可能小,在水平方向上尽可能大。而西和东在水平方向上尽可能小,在垂直方向上尽可能大。中心的版面化对象则填充了剩余的空间。 GridLayout :用了一些行和列,创建一个栅格,用户可以向其中增加控件。栅格中的每个成员大小都相同,按照它们增加的顺序,从左到右沿着行分布。 FlowLayout :试图向一个水平行中增加控件,一旦这行对于容器的宽度来说太大了,就开始新的一行。可以向左、中央和右看齐。 在 GUI 创建中使用这些类是很简单的。当创建一个其中包含其它控件的控件时,将其包装在一个 ContainerBox中,设置盒子的版面,然后向盒子中增加所有的子控件。唯一没有增加到ContainerBox中的控件是最顶部级别的控件,它通常是一个表单,被包装在一个AreaPane或一个 ResizeablePane中。一个ResizeablePane将采用其母控件的形状,但是一个AreaPane 则是所指定区域的形状。 上图是一个用版面库开发的GUI。以下是布置控件的代码,其中用注释取代了附加部分。 |
public class CalculatorForm : Form { public CalculatorForm() { Size = new Size(200, 250); Text = "Calculator"; myCalculator = new Calculator(); //This will be the top-level pane to which all other controls will be added //and which also resizes as the Form is resized. AreaPane controlPane = new ResizeablePane(this, ClientRectangle, new BorderLayout()); myTextBox = new TextBox(); myTextBox.Text = "0"; //Notice that the control is added to the pane. ContainerBoxes will //add all controls which are added to them to their boxed control automatically. controlPane.Add(myTextBox, BorderLayout.Direction.North); Panel p = new Panel(); //Since buttonPane will have other controls added to it, it is wrapped in //a ContainerBox. ContainerBox buttonPane = new ContainerBox(p); addButtons(buttonPane); Button clearB = new Button(); clearB.Text = "Clear"; clearB.Click += new EventHandler(clear); controlPane.Add(clearB, BorderLayout.Direction.South); controlPane.Add(buttonPane, BorderLayout.Direction.Center); } private void addButtons(ContainerBox pane) { pane.layoutManager = new GridLayout(4, 3); for(int i=1; i<10; i++){ Button b = getDigitButton(i); pane.Add(b); } Button zero = getDigitButton(0); Button plus = getButton("+"); Button minus = getButton("-"); plus.Click += new EventHandler(action); minus.Click += new EventHandler(action); pane.Add(plus); pane.Add(zero); pane.Add(minus); } //private methods called by the constructor //... } |