swing入门教程(五) swing其他重要概念

  ——关于Swing 布局、事件和模型。


既然您已经知道了大多数(肯定不是全部)可以用来制作 UI 的组件,那么就必须实际用它们做些什么。您不能只是随意地把它们放在屏幕上,然后就指望它们立即就能工作。您必须把它们放在特定的点上,对它们的交互作出反应,然后根据交互更新它们,用数据填充它们。要填满 UI 知识的这片空白,还需要更多地学习 UI 的其他重要部分。

所以,让我们来研究以下内容:

 

  • 布局:Swing 包括许多布局,布局也是类,负责处理组件在应用程序中的摆放位置,以及在应用程序改变尺寸或者删除、添加组件时对组件进行相应处理。

  • 事件:您需要对按下按钮、单击鼠标和用户在 UI 上能做的每件事进行响应。想像一下,如果不能响应会发生什么 —— 用户单击之后,什么变化也没有。

  • 模型: 对于更高级的组件(列表、表格和树),以及一些像 JComboBox 这样的更容易的组件来说,模型是处理数据最有效的途径。它们把大部分处理数据的工作从实际的组件本身撤出来(请回想一下前面讨论的 MVC),并提供了一个公共数据对象类(例如VectorArrayList)的包装器。

简单布局

就像在前面提到过的,布局替您处理组件在应用程序中的摆放。您的第一个问题可能是“为什么不能用像素告诉它应当在什么地方呢?”是的,您可以这样做,但是在窗口改变大小的时候,或者更糟一些情况,即用户改变其屏幕的分辨率的时候,亦或在有人想在其他操作系统上试用应用程序的时候,您立刻就会遇到麻烦。布局管理器把这些担心一扫而空。不是每个人都用相同的设置,所以布局管理器会创建“相对”布局,允许您指定组件相对于其他组件的摆放方式,决定事物改变尺寸的方式。这是好的部分:比听起来更容易。只要调用setLayout(yourLayout) 设置布局管理器即可。后面对add() 的调用可以将组件添加到容器中,并让布局管理器负责将它放在应当的位置上。

目前在 Swing 中包含了大量布局;看起来好象每次发布都会有一个新布局负责不同的目的。但是,有些经过实践检验的布局一直存在,而且会永远存在,我指的是永远 —— 因为从 1995 年 Java 语言的第一个发行版开始,就有这些布局。这些布局是:FlowLayout、GridLayout 和 BorderLayout。

FlowLayout 从左到右安排组件。当空间不足时,就移到下一行。它是使用起来最简单的布局,因此,也就是能力最弱的布局:

   setLayout(new FlowLayout());   add(new JButton("Button1"));   add(new JButton("Button2"));   add(new JButton("Button3"));

FlowLayout 实例
FlowLayout

GridLayout 就像您想像的那样工作:它允许指定行和列的数量,然后在添加组件时把组件放在这些单元格中:

   setLayout(new GridLayout(1,2));    add(new JButton("Button1"));   add(new JButton("Button2"));   add(new JButton("Button3"));

GridLayout 实例
GridLayout

即使 Swing 中添加了许多新的布局管理器,BorderLayout 仍然是其中非常有用的一个。即使有经验的 UI 开发人员也经常使用 BorderLayout。它使用东、南、西、北、中的概念在屏幕上放置组件:

   setLayout(new BorderLayout());   add(new JButton("Button1"), "North");   add(new JButton("Button2"), "Center");   add(new JButton("Button3"), "West");

BorderLayout 实例
BorderLayout

 GridBagLayout

虽然上面的示例对于简单的布局来说很好,但是更高级的 UI 需要更高级的布局管理器。这是 GridBagLayout 发挥作用的地方。不幸的是,使用它的时候极易混淆、极为困难,每个曾经用过它的人都会同意这点。我也不能反对;但是除了它的困难之外,它可能是用 Swing 内置的布局管理器创建漂亮 UI 的最好方式。

以下是我的第一个小建议:在最新版的 Eclipse 中,有内置的可视化构建器,这个个小建议可以自动根据每个屏幕的需要来构建必需的 GridBagLayout 代码。请使用这个功能!它会节约无数为了让数字正确而浪费的时间。所以在我用这一节解释 GridBagLayout 如何工作、如何调整它才能让它做得最好时,建议您去找一个可视化构建器并生成代码。它会节约您的工作时间

事件

最后,我们来到 Swing 最重要的一部分:处理事件,对 UI 的交互作出反应。Swing 用事件/侦听器模型处理事件。这个模型的工作方式是:允许某个类登记到某个组件的某个事件上。登记到事件的这个类叫做侦听器,因为它等候组件的事件发生,而且在事件发生时采取行动。组件本身知道如何“激活”事件(即,知道它能生成的交互类型,以及如何让侦听器知道这个交互什么时候发生)。组件与包含有关交互信息的事件和类针对交互进行通信。

把技术方面的空谈放在一边,我们来看几个 Swing 中事件的实例。首先从最简单的示例开始,即一个 JButton,按下它的时候,会在控制台上输出“Hello”。

JButton 知道它什么时候被按下;这是在内部处理的,不需要代码处理它。但是,侦听器需要进行登记,以接收来自 JButton 的事件,这样您才能输出“Hello”。listener 类通过实现listener 接口然后调用 JButton 上的addActionListener() 做到这一点:

   // Create the JButton   JButton b = new JButton("Button");   // Register as a listener   b.addActionListener(new HelloListener());   class HelloListener implements ActionListener   {      // The interface method to receive button clicks      public void actionPerformed(ActionEvent e)      {         System.out.println("Hello");      }   }

JList 也用类似的方式工作。当有人在 JList 中选中什么时,您可能想把选中的对象输出到控制台上:

   //  myList is a JList populate with data   myList.addListSelectionListener(new ListSelectionListener()   {      public void valueChanged(ListSelectionEvent e)      {         Object o = myList.getSelectedItem();         System.out.println(o.toString());      }   }   );

从这两个示例,您应当能够理解事件/侦听器模型在 Swing 中如何工作了。实际上,Swing 中的每个交互都是以这种方式处理的,所以通过理解这个模型,您就立即能够理解在 Swing 中如何处理每个事件,以及如何对用户可能抛给您的任何交互做反应了。

模型

现在,您应当了解了 Java 的集合(Collection),这是一组处理数据的 Java 类。这些类包括 ArrayListHashMapSet。大多数应用程序在反复处理数据时,经常用这些类。但是,当需要在 UI 中使用这些数据类时,出现了一个限制。UI 不知道如何显示它们。请先想一分钟。如果有一个JList 和一个某种数据对象(例如Person 对象)的ArrayListJList 怎样才能知道要显示什么?它是要显示某个人的名字,还是连名带姓一起显示?

这就是模型的概念发挥作用的地方了。虽然模型这个术语表达的范围更大,但是在本教程的示例中,我用 UI 模型这个术语描述组件用来显示数据的类。

在 Swing 中每个处理集合数据的的组件都采用模型的概念,而且这也是使用和操纵数据的首选方法。它清晰地把 UI 的工作与底层数据分开(请回想 MVC 示例)。模型工作的机制是向组件描述如何显示集合数据。我说的“描述”指的是什么呢?每个组件需要的描述略有不同:

 

  • JComboBox 要求其模型告诉它把什么文本作为选项显示,以及有多少选项。

  • JSpinner 要求其模型告诉它显示什么文本,前一个和下一个选择是什么。

  • JList 也要求其模型告诉它把什么文本作为选项显示,存在多少选项。

  • JTable 要求的更多:它要求模型告诉它存在多少列和多少行,列名称、每列的类以及在每个单元格中显示什么文本。

  • JTree 要求它的模型告诉它整个树的根节点、父节点和子节点。

 

您可能会问:为什么要做这么些工作?为什么要把这些功能分开?请想像以下场景:您有一个复杂的 JTable,有许多列数据,您在许多不同的屏幕上使用这个表格。如果您突然决定删除某个列,那么怎么做会更容易呢?修改您使用的每个 JTable 实例中的代码?还是创建一个可以在每个 JTable 实例中使用的模型类,然后只修改这一个模型类呢?显然,所做的修改越少越好。

模型示例

我们来看看模型如何工作,在一个简单的 JComboBox 示例中使用模型。在 JComboBox 前面的演示中,我介绍了如何调用 setItem() 向数据中添加项目。虽然对于简单的演示,这样做可以接受,但是在实际的应用程序中很少这么用。毕竟,在有 25 个选项,而且选项不断变化的时候,您还真的想每次都调用addItem() 25 次对这些选项进行迭代吗?当然不是。

JComboBox 包含一个方法调用 setModel(),它接受ComboBoxModel 类的实例。应当用这个方法代替addItem() 方法来创建 JComboBox 中的数据。

假设有一个 ArrayList,其中使用字母表作为其数据(“A”、“B”、“C” ,等等):

   MyComboModel model = new MyComboModel(alphaList);   myComboBox.setModel(model);      public class MyComboModel implements ComboBoxModel   {      private List data = new ArrayList();      private int selected = 0;      public MyComboModel(List list)      {         data = list;      }      public void setSelectedItem(Object o)      {         selected = data.indexOf(o);      }      public Object getSelectedItem()      {         return data.get(selected);      }      public int getSize()      {         return data.size();      }      public Object getElementAt(int i)      {         return data.get(i);      }   }

采用模型时更好的地方是:您可以反复重用它。例如,假设 JComboBox 的数据需要从字母表变成 1 到27 的数字。那么只用一行就可以实现这个变化:用新的数据List 添加 JComboBox,不需要使用额外的代码:

   myComboBox.setModel(new MyComboModel(numberList));

模型在 Swing 中是非常有好处的特性,因为它们提供了代码重用功能,而且使数据处理更加容易。更常见的应用是在大型应用程序中,服务器端开发人员创建和检索数据,并把数据传递给 UI 开发人员。如何处理这些数据和正确地显示它们,取决于 UI 开发人员,而模型就是实现这项任务的工具。


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值