需求秋千_秋千简介

在你开始前

关于本教程

本教程适用于Swing初学者。 也许您认识使用它的其他人,或者您已经在使用的应用程序中看到它。 也许您自己也涉猎了它。 无论如何,本教程将从无处不在的HelloWorld应用程序开始,向您介绍一个基本的Swing应用程序。 在您的机器上运行该程序之后,我们将通过创建航班预订系统并在您拥有基本但功能齐全的应用程序之前将其添加到您的Swing知识中。

在本教程的过程中,您将学习Swing中的所有初学者组件。 对于初学者组件,我的意思是指用于构建简单用户界面(UI)的组件。 您将学习如何使用基本方法来设置其属性,以及这些Swing组件如何与其他组件交互。 您还将了解完成Swing知识所需的其他UI概念,包括布局,事件/侦听器和数据模型。 在教程结束之前,您应该能够构建一个简单的Swing应用程序。

请注意,尽管本教程并非旨在作为Swing的所有入门指南。 整本书籍都是专门学习Swing的,在这里我可能无法重复。 相反,本教程重点介绍初学者最有可能在您的工作中遇到的最常用的组件和功能。

如果在完成本教程之后,您有兴趣进一步了解Swing编程,则应该阅读名为“ Intermediate Swing ”的配套教程,该教程将以本教程中开发的概念和示例应用程序为基础。

工具和源下载

要完成本教程,您将需要以下内容:

秋千简介

UI介绍

在开始学习Swing之前,您必须解决真正的初学者的问题:什么是UI? 好吧,初学者的答案是“用户界面”。 但是,由于本教程的目的是确保您不再仅仅是一个初学者,因此我们需要一个更高级的定义。

所以,我再次提出问题:什么是UI? 嗯,您可以通过说它是您按下的按钮,您键入的地址栏以及您打开和关闭的窗口来定义它,这些都是UI的元素,但是它所具有的不仅仅是屏幕上显示的内容。 。 UI中包含鼠标,键盘,音乐音量,屏幕上的颜色,使用的字体以及与另一个对象相比的对象位置。 基本上,任何在计算机和用户之间的交互中起作用的对象都是UI的一部分。 这似乎很简单,但您会惊讶地发现,多年来有许多人和大型公司搞砸了这一点。 实际上,现在有一些大学专业的唯一课程就是研究这种相互作用。

秋千的作用

Swing是Java平台的UI,它充当处理用户与计算机之间所有交互的软件。 它实质上是充当用户和计算机胆量之间的中间人。 Swing到底如何做到这一点? 它提供了处理上一版中介绍的UI方面的机制:

  • 键盘:Swing提供了一种捕获用户输入的方法。
  • 颜色:Swing提供了一种更改屏幕上显示的颜色的方法。
  • 您键入的地址栏:Swing提供了处理所有普通任务的文本组件。
  • 音乐的音量:嗯... Swing并不完美。

无论如何,Swing为您提供了创建自己的UI所需的所有工具。

MVC

Swing甚至更进一步,并将通用的设计模式置于基本的UI原则之上。 这种设计模式称为模型视图控制器(MVC),旨在“分离角色”。 MVC使代码负责如何将某些事物与代码分开,以处理与响应交互并驱动更改的代码分开的数据。

困惑? 如果我在现实世界中为您提供这种设计模式的非技术示例,会更容易。 想想一场时装秀。 考虑一下您的UI,并假装衣服是数据,即您提供给用户的计算机信息。 现在,想象一下这个时装秀只有一个人。 这个人设计衣服,修改衣服,然后同时沿着跑道走下去。 这似乎不是一个结构合理或有效的设计。

现在,考虑使用MVC设计模式进行的同一场时装秀。 角色由人来代替,而不是一个人做。 时装模特(不要与首字母缩略词MVC的模型混淆)展示衣服。 它们充当视图。 他们知道显示衣服(数据)的正确方法,但对如何创建或设计衣服一无所知。 另一方面,服装设计师在后台进行工作,必要时对衣服进行更改。 设计者充当控制器。 这个人没有如何走跑道的概念,但是可以创造和操纵衣服。 时装模特和设计师都独立于衣服工作,并且都具有专业知识。

这就是MVC设计模式背后的概念:让UI的每个方面都处理其擅长的方面。 如果您仍然感到困惑,则本教程其余部分中的示例将有望缓解这种情况-但请在继续操作时牢记基本原理:可视化组件显示数据,其他类对其进行操作。

组件

整个Swing可视组件库的基本构建块是JComponent 。 这是每个组件的超类。 这是一个抽象类,因此您实际上不能创建JComponent ,但是它实际上包含了数百个函数,这些函数可以作为类层次结构的结果而在Swing中的每个组件使用。 显然,某些概念比其他概念更重要,因此对于本教程而言,要学习的重要事项是:

  • JComponent不仅是Swing组件的基类,也是自定义组件的基类(有关更多信息,请参见“ Intermediate Swing ”教程)。
  • 它提供了所有组件的绘制基础结构,这对于自定义组件非常有用(同样,“ Intermediate Swing ”中有关于此主题的更多信息)。
  • 它知道如何处理所有键盘按键。 然后,子类仅需要侦听特定的键。
  • 它包含add()方法,使您可以添加其他JComponent 。 从另一种角度来看,您似乎可以将任何Swing组件添加到任何其他Swing组件以构建嵌套的组件(例如,包含JButton的JPanel,甚至是更奇怪的组合,例如包含JButton的JMenu)。

简单的Swing小部件

杰贝

Swing库中最基本的组件是JLabel。 它完全符合您的期望:它坐在那里,看起来很漂亮,并描述了其他组件。 下图显示了正在运行的JLabel:

JLabel

杰贝

不是很令人兴奋,但仍然有用。 实际上,您在整个应用程序中不仅将JLabel用作文本描述,还用作图片描述。 每当您在Swing应用程序中看到图片时,就有可能是JLabel。 对于您期望的初学者来说,JLabel没有很多方法可以用于Swing初学者。 基本方法涉及设置标签描述的文本,图像,对齐方式和其他组件:

  • get/setText()获取/设置标签中的文本。
  • get/setIcon()获取/设置标签中的图像。
  • get/setHorizontalAlignment()获取/设置文本的水平位置。
  • get/setVerticalAlignment()获取/设置文本的垂直位置。
  • get/setDisplayedMnemonic()获取/设置标签的助记符(带下划线的字符)。
  • get/setLabelFor()获取/设置此标签附加到的组件; 因此,当用户按下Alt +记忆键时,焦点将移至指定的组件。

JButton

Swing中的基本动作组件JButton是在每个窗口中都带有“确定”和“取消”的按钮。 它的功能与您期望按钮的功能完全相同-单击它会发生一些事情。 到底发生了什么? 好了,您必须对其进行定义(有关更多信息,请参见事件 )。 运行中的JButton如下所示:

JButton

JButton

用于更改JButton属性的方法与JLabel方法类似(并且您会在大多数Swing组件中发现它们相似)。 它们控制文本,图像和方向:

  • get/setText()获取/设置按钮中的文本。
  • get/setIcon()获取/设置按钮中的图像。
  • get/setHorizontalAlignment()获取/设置文本的水平位置。
  • get/setVerticalAlignment()获取/设置文本的垂直位置。
  • get/setDisplayedMnenomic()获取/设置助记符(带下划线的字符),当与Alt按钮结合使用时,将导致该按钮单击。

除了这些方法之外,我还将介绍JButton包含的另一组方法。 这些方法利用了按钮的所有不同状态。 状态是描述组件的属性,通常使用true / false设置。 对于JButton,它包含以下可能的状态:活动/非活动,已选择/未选择,鼠标悬停/鼠标关闭,按下/未按下。 另外,您可以组合状态,以便例如可以将鼠标悬停在按钮上。 现在,您可能会问自己,应该对所有这些状态进行什么操作。 例如,转到浏览器上的“后退”按钮。 请注意,将鼠标悬停在图像上时,图像会发生变化,而按下图像时,图像会发生变化。 此按钮利用各种状态。 在每个状态下使用不同的图像是一种向用户表明正在发生交互的流行且有效的方法。 JButton上的状态方法是:

  • get/setDisabledIcon()
  • get/setDisabledSelectedIcon()
  • get/setIcon()
  • get/setPressedIcon()
  • get/setRolloverIcon()
  • get/setRolloverSelectedIcon()
  • get/setSelectedIcon()

JTextField

Swing中的基本文本组件是JTextField,它允许用户在UI中输入文本。 我确定您熟悉一个文本字段; 您必须输入一个用户名和密码才能使用本教程。 您输入文本,删除文本,突出显示文本并四处移动插入符号-Swing会为您处理所有这些操作。 作为UI开发人员,利用JTextField几乎不需要做任何事情。

无论如何,JTextField的实际效果如下:

JTextField

JTextField

处理JTextField时,您只需要关心一种方法-这应该很明显-设置文本的方法: get/setText() ,该方法获取/设置JTextField中的文本。

J框架

到目前为止,我已经讨论了Swing的三个基本构建块,标签,按钮和文本字段。 但是现在您需要在某个地方放置它们。 它们不能只是在屏幕上浮动,而是希望用户知道如何处理它们。 JFrame类就是这样做的-它是一个容器,可让您向其中添加其他组件以组织它们并将其呈现给用户。 它包含许多其他奖金,但我认为最先看到它的图片是最容易的:

J框架

J框架

实际上,JFrame所做的不仅仅是让您在其上放置组件并将其呈现给用户。 尽管看起来很简单,但它实际上是Swing软件包中最复杂的组件之一。 为了大大简化原因,JFrame充当了独立于OS的Swing部件与其运行的实际OS之间的桥梁。 JFrame在本机OS中注册为窗口,这样便获得了许多熟悉的OS窗口功能:最小化/最大化,调整大小和移动。 但是,出于本教程的目的,将JFrame视为放置组件的面板就足够了。 您可以在JFrame上调用以更改其属性的一些方法是:

  • get/setTitle()获取/设置框架的标题。
  • get/setState()获取/设置要最小化,最大化等的帧。
  • is/setVisible()获取/设置要在屏幕上可见的框架。
  • get/setLocation()获取/设置屏幕上应该显示框架的位置。
  • get/setSize()获取/设置框架的大小。
  • add()将组件添加到框架。

一个简单的应用

像所有“ x入门”教程一样,该教程具有必要的HelloWorld演示。 但是,该示例不仅对查看Swing应用程序的工作方式很有用,而且对确保设置正确无用。 一旦您使这个简单的应用程序开始工作,此示例之后的每个示例也将正常工作。 下图显示了完整的示例:

HelloWorld示例

你好,世界

第一步是创建类。 将组件放置在JFrame上的Swing应用程序需要JFrame类,如下所示:

public class HelloWorld extends JFrame

这样,您将获得上面概述的所有JFrame属性,最重要的是该窗口的本机OS支持。 下一步是将组件放置在屏幕上。 在本示例中,您使用空布局。 您将在本教程的后面部分了解有关布局和布局管理器的更多信息。 但是,对于此示例,数字表示JFrame上的像素位置:

public HelloWorld()
   {
      super();
      this.setSize(300, 200);
      this.getContentPane().setLayout(null);
      this.add(getJLabel(), null);
      this.add(getJTextField(), null);
      this.add(getJButton(), null);
      this.setTitle("HelloWorld");
   }

   private javax.swing.JLabel getJLabel() {
      if(jLabel == null) {
         jLabel = new javax.swing.JLabel();
         jLabel.setBounds(34, 49, 53, 18);
         jLabel.setText("Name:");
      }
      return jLabel;
   }

   private javax.swing.JTextField getJTextField() {
      if(jTextField == null) {
         jTextField = new javax.swing.JTextField();
         jTextField.setBounds(96, 49, 160, 20);
      }
      return jTextField;
   }

   private javax.swing.JButton getJButton() {
      if(jButton == null) {
         jButton = new javax.swing.JButton();
         jButton.setBounds(103, 110, 71, 27);
         jButton.setText("OK");
      }
      return jButton;
   }

既然组件已放置在JFrame上,则需要JFrame出现在屏幕上并使您的应用程序可运行。 像在所有Java应用程序中一样,您必须添加main方法以使Swing应用程序可运行。 在这个主要方法中,您只需要创建HelloWorld应用程序对象,然后在其上调用setVisible()

public static void main(String[] args)
   {
      HelloWorld w = new HelloWorld();
      w.setVisible(true);
   }

大功告成! 这就是创建应用程序的全部。

其他Swing小部件

J组合框

在本节中,我们将介绍Swing库中的所有其他组件,如何使用它们以及它们的外观,这应该使您更好地了解Swing作为UI开发人员所具有的功能。

我们将从JComboBox开始。 组合框是常见的下拉选择,用户可以从列表中选择任何一项,也可以选择一项(只有一项)。 在组合框的某些版本中,您可以键入自己的选择。 一个很好的例子是浏览器中的地址栏。 这是一个组合框,可让您键入自己的选择。 这是JComboBox在Swing中的外观:

JComboBox

J组合框

JComboBox的重要功能涉及其中包含的数据。 您需要一种方法来设置JComboBox中的数据,进行更改,并在用户做出选择后获得用户的选择。 您可以使用以下JComboBox方法:

  • addItem()将项目添加到JComboBox。
  • get/setSelectedIndex()获取/设置JComboBox中所选项目的索引。
  • get/setSelectedItem()获取/设置所选对象。
  • removeAllItems()从JComboBox移除所有对象。
  • remoteItem()从JComboBox移除特定对象。

JPasswordField

JTextField的略微变化是JPasswordField,它使您可以隐藏显示在文本字段区域中的所有字符。 毕竟,每个人键入时都能读懂的密码有什么用? 可能一点都不好,在当今这样的时代,您的私有数据容易受到攻击,您需要获得所有可能的帮助。 这是JPasswordField在Swing中的外观:

JPasswordField

JPasswordField

JPasswordField上的其他“安全”方法会稍微改变JTextField的行为,因此您无法阅读文本:

  • get/setEchoChar()每次输入字符时,获取/设置出现在JPasswordField中的字符。 收到密码后不会返回“ echo”。 而是返回实际字符​​。
  • getText()你不应该使用这个功能,因为它可能带来的安全问题(对于那些有兴趣,该字符串将被保存在内存中,并且可能堆转储可能透露密码)。
  • getPassword()这是从JPasswordField获取密码的正确方法,因为它返回包含密码的char[] 。 为了确保适当的安全性,应将阵列清除为0,以确保其不保留在内存中。

JCheckBox / JRadioButton

JCheckBox和JRadioButton组件通常以多项选择格式向用户提供选项。 有什么不同? 从实际的角度来看,它们没有什么不同。 它们的行为方式相同。 但是,在常见的UI惯例中,它们有一个细微的区别:JRadioButton通常组合在一起,以向用户提供带有强制性答案的问题,并且这些答案是排他的(意味着该问题只能有一个答案)。 JRadioButton的行为强制执行此用法。 一旦选择了JRadioButton,就无法取消选择它,除非您在组中选择另一个单选按钮。 实际上,这使选择变得唯一且必不可少。 JCheckBox的不同之处在于,它允许您随机选择/取消选择,并允许您选择问题的多个答案。

这是一个例子。 问题“你是男是女?” 导致两个唯一的答案选择“男人”或“女孩”。 用户必须选择一个,不能同时选择两个。 另一方面,问题“您的爱好是什么?” 答案为“跑步”,“睡觉”或“阅读”的答案不应只允许一个答案,因为人们可能有多个兴趣。

将这些JCheckBoxes或JRadioButtons的组联系在一起的类是ButtonGroup类。 它使您可以将选项(例如“ Guy”和“ Girl”)分组在一起,以便在选择一个选项时自动取消选择另一个选项。

这是Swing中JCheckBox和JRadioButton的外观:

JCheckBox和JRadioButton

JCheckBox / JRadioButton

要记住的重要ButtonGroup方法是:

  • add()将JCheckBox或JRadioButton添加到ButtonGroup。
  • getElements()获取ButtonGroup中的所有组件,使您可以迭代它们以找到选定的组件。

JMenu / JMenuItem / JMenuBar

JMenu,JMenuItem和JMenuBar组件是在JFrame上开发菜单系统的主要构建块。 任何菜单系统的基础都是JMenuBar。 这很简单,很无聊,但这是必需的,因为每个JMenu和JMenuItem都是基于它构建的。 您可以使用setJMenuBar()方法将JMenuBar附加到JFrame。 将其锚定到JFrame之后,您可以添加所需的所有菜单,子菜单和菜单项。

JMenu / JMenuItem的差异可能看起来很明显,但实际上是在幕后,而不是看起来。 如果查看类层次结构,则JMenuJMenuItem的子类。 但是,从表面上看,它们有所不同:您使用JMenu包含其他JMenuItems和JMenus; 选择JMenuItems会触发动作。

JMenuItem还支持快捷键的概念。 与您使用的大多数应用程序一样,Swing应用程序允许您按Ctrl +(一个键)来触发操作,就像选择菜单项本身一样。 考虑一下您用于剪切和粘贴的Ctrl + X和Ctrl + V。

此外,JMenu和JMenuItem均支持助记符。 您可以结合使用Alt键和字母来模仿菜单本身的选择(例如,按Alt + F,然后Alt + x将关闭Windows中的应用程序)。

这是带有JMenus和JMenuItems的JMenuBar在Swing中的外观:

JMenuBar,JMenu和JMenuItem

JMenuBar / JMenu / JMenuItem

这些类所需的重要方法是:

  • JMenuItem和JMenu:
    • get/setAccelerator()获取/设置用于快捷键的Ctrl +键。
    • get/setText()获取/设置菜单文本。
    • get/setIcon()获取/设置菜单中使用的图像。
  • 仅JMenu:
    • add()将另一个JMenu或JMenuItem添加到JMenu(创建嵌套菜单)。

JSlider

您可以在应用程序中使用JSlider来允许更改数值。 这是一种快速简便的方法,它使用户不仅可以直观地获得有关当前选择的反馈,还可以直观地获得可接受值范围的反馈。 如果您考虑一下,您可以提供一个文本字段并允许您的用户输入一个值,但是您会遇到麻烦,即要确保该值是一个数字并且也要适合所需的数字范围。 例如,如果您有一个金融网站,并询问要投资股票的百分比,则必须检查在文本字段中键入的值,以确保它们是数字,且介于0到100之间。如果改用JSlider,则可以确保所选内容是在所需范围内的数字。

在Swing中,JSlider如下所示:

JSlider

JSlider

JSlider中的重要方法是:

  • get/setMinimum()获取/设置您可以选择的最小值。
  • get/setMaximum()获取/设置您可以选择的最大值。
  • get/setOrientation()获取/设置JSlider为上/下或左/右滑块。
  • get/setValue()获取/设置JSlider的初始值。

JSpinner

与JSlider一样,您可以使用JSpinner允许用户选择一个整数值。 与JSlider相比,JSlider的一大优势是其紧凑的空间。 但是,它的缺点是您无法轻松设置其界限。

但是,两个组件之间的比较到此结束。 JSpinner更加灵活,可用于在任何一组值之间进行选择。 除了在数字之间选择之外,它还可以用于在日期,名称,颜色或其他任何东西之间进行选择。 通过允许您提供仅包含预定选项的组件,这使得JSpinner极其强大。 这样,它类似于JComboBox,尽管它们的使用不应互换。 您应该仅将JSpinner用于逻辑上连续的选择-数字和日期是最合理的选择。 另一方面,JComboBox是呈现看似随机的选择的更好选择,这些选择在一个选择与另一个选择之间没有联系。

JSpinner看起来像这样:

JSpinner

JSpinner

重要的方法是:

  • get/setValue()获取/设置JSpinner的初始值,在基本实例中,该初始值必须为整数。
  • getNextValue()获取按下向上箭头按钮后将选择的下一个值。
  • getPreviousValue()获取按下向下箭头按钮后将选择的上一个值。

工具栏

JToolBar充当其他组件(JButton,JComboBoxes等)的面板,这些组件共同构成了大多数应用程序中您熟悉的工具栏。 工具栏允许程序将常用命令放置在快速找到的位置,并将它们分组为常见命令组。 通常,但并非总是如此,工具栏按钮在菜单栏中具有匹配的命令。 尽管这不是必需的,但它已成为常见的做法,您也应尝试这样做。

JToolBar还提供了您在其他工具栏中看到的另一个功能,即“浮动”功能(即成为主框架顶部的独立框架)。

下图显示了一个非浮动的JToolBar:

非浮动JToolBar

非浮动JToolBar

使用JToolBar要记住的重要方法是: is/setFloatable() ,它获取/设置JToolBar是否可以浮动。

JToolTip

您可能在各处都看到过JToolTips,但从未知道它们的名字。 它们有点像鞋带末端的塑料部件-它们无处不在,但您不知道专有名称(如果您想知道的话,它们称为aglets )。 JToolTips是将鼠标悬停在某物上时弹出的小“气泡”。 它们在应用程序中非常有用,可以为难于使用的项目提供帮助,扩展信息,甚至在拥挤的UI中显示项目的完整文本。 通过将鼠标悬停在组件上一定时间,可以在Swing中触发它们。 它们通常在鼠标变为非活动状态后大约一秒钟出现。 只要鼠标停留在该组件上,它们就保持可见。

关于JToolTip的重要之处在于它的易用性。 setToolTip()方法是JComponent类中的一种方法,这意味着每个Swing组件都可以具有与其关联的工具提示。 尽管JToolTip本身是Swing类,但目前它确实不提供任何其他功能来满足您的需求,因此不应自行创建。 您可以通过在JComponent中调用setToolTip()函数来访问和使用它。

这是一个JToolTip的样子:

JToolTip

JToolTip

JOptionPane

JOptionPane是Swing中的“快捷方式”类。 通常,作为UI开发人员,您想向用户显示一条快速消息,让他们知道错误或某些信息。 您甚至可能试图获取一些快速数据,例如姓名或电话号码。 在Swing中, JOptionPane类为这些相当平凡的任务提供了快捷方式。 Swing提供了这个基本但有用的类,而不是让每个开发人员都重新创建轮子,而是为UI开发人员提供了一种获取和接收简单消息的简便方法。

这是一个JOptionPane:

JOptionPane

JOptionPane

使用JOptionPane时,有些棘手的部分是您可以使用的所有可能选项。 尽管简单,但它仍然提供了许多可能引起混淆的选项。 学习JOptionPane的最好方法之一就是尝试使用它。 对其进行编码,然后查看弹出的内容。 该组件使您几乎可以改变它的各个方面:框架的标题,消息本身,显示的图标,按钮的选择以及是否需要文本响应。 在本教程的此处列出的可能性太多了,最好的选择是访问JOptionPane API页面以查看其许多可能性。

JTextArea

JTextArea使JTextField更进一步。 虽然JTextField限于一行文本,但JTextArea通过允许多行文本来扩展了此功能。 可以将其视为一个空白页面,使您可以在其中的任何位置键入内容。 您可能会猜到,JTextArea包含许多与JTextField相同的功能。 毕竟,它们实际上是完全相同的组成部分。 但是,JTextArea提供了一些其他重要功能,使其与众不同。 这些功能包括自动换行的功能(即,将长单词换行而不是中间单词切开)和自动换行的功能(即,将长行文本移至下一行)创建一条很长的线需要水平滚动条)。

Swing中的JTextArea看起来像您可能期望的那样:

一个JTextArea

JTextArea

启用换行和自动换行的重要方法是:

  • is/setLineWrap()设置行过长时是否应该换行。
  • is/setWrapStyleWord()设置太长的单词是否应移至下一行。

JScrollPane

在上面的示例的基础上,假设JTextArea包含太多文本以致无法在给定空间中包含。 那呢 不幸的是,如果您认为滚动条会自动出现,那是错误的。 但是,JScrollPane填补了这一空白,提供了一个Swing组件来处理所有与滚动条相关的动作。 因此,为可能需要它的每个组件提供一个滚动窗格可能会有些麻烦,但是一旦添加了它,它就会自动处理所有内容,包括在需要时隐藏/显示滚动条。

除了使用要包装的组件创建JScrollPane之外,您不必直接处理JScrollPane。 在上面的示例的基础上,通过使用JTextArea调用JScrollPane构造函数,可以创建当文本过长时JTextArea滚动的功能:

JScrollPane scroll = new JScrollPane(getTextArea());
   add(scroll);

此更新的示例如下所示:

JScrollPane示例

JScrollPane

JScrollPane还公开了它将创建的两个JScrollBar。 这些JScrollBar组件还包含可用于更改其行为的方法(尽管它们不在本教程的讨论范围之内)。

使用JScrollPane所需的方法是:

  • getHorizontalScrollBar()返回水平JScrollBar组件。
  • getVerticalScrollBar():返回垂直的JScrollBar组件。
  • get/setHorizontalScrollBarPolicy()此“策略”可以是三件事之一:始终,从不或根据需要。
  • get/setVerticalScrollBarPolicy()与水平函数相同。

列表

JList是一个有用的组件,用于向用户显示许多选择。 您可以将其视为JComboBox的扩展。 JList提供了更多选择,并增加了多项选择的功能。 JList和JComboBox之间的选择通常归结于以下两个功能:如果需要多个选择,或者如果这些选项包括15个以上的选择(尽管该数字不是一般规则),则应始终选择JList。

如上所示,您应该将JList与JScrollPane结合使用,因为它提供的选项多于其空间可容纳的范围。

JList包含选择模型的概念(在JTables中也可以看到),您可以在其中设置JList接受不同类型的选择。 这些类型是单一选择,您只能选择一个选择;单一间隔选择,您只能选择连续的选择,但是可以根据需要选择多个选择;或者多重间隔选择,您可以在任何选择中选择任意数量的选择组合。

JList是我所谓的“复杂组件”中的第一个,其中还包括JTable和JTree,它们允许进行大量的自定义更改,包括更改UI的外观以及如何处理数据。 因为本教程仅努力介绍基础知识,所以我将不涉及这些更高级的功能,但是在使用这些组件时要记住一些东西-与目前为止介绍的那些组件相比,它们提出了更艰巨的挑战。

JList在Swing中看起来像这样:

JList

列表

JList中有许多功能可以处理数据,正如我所说,这些功能只是涉及使用JList进行详细工作所需的所有内容。 以下是基本方法:

  • get/setSelectedIndex()获取/设置列表的选定行; 如果是多选列表,则返回int[]
  • get/setSelectionMode()如上所述,获取/设置选择模式为单个,单个间隔或多个间隔。
  • setListData()设置要在JList中使用的数据。
  • get/setSelectedValue()获取选定的对象(与选定的行号相对)。

JTable

当您想到JTable时,请考虑一下Excel电子表格,这应该使您清楚了解JTable在Swing中的功能。 它具有许多相同的特征:单元格,行,列,移动列和隐藏列。 JTable使JList的思想更进一步。 它不是将数据显示在一列中,而是将其显示在多列中。 让我们以一个人为例。 JList只能显示一个人的一个属性-例如,他或她的名字。 但是,JTable可以显示多个属性-名称,年龄,地址等。JTable是Swing组件,它使您能够提供有关数据的最多信息。

不幸的是,作为一种折衷,它也是众所周知地最难解决的Swing组件。 许多UI开发人员在尝试学习JTable的每个细节时都感到头疼。 我希望能从这里节省您的时间,并且只需借助您的JTable知识就可以使事情如鱼得水。

JList中的许多相同概念也扩展到JTables,例如,包括不同选择间隔的想法。 但是,JList的单行概念更改为JTable的单元结构。 这意味着您可以采用不同的方式在JTables中进行选择,例如列,行或单个单元格。

在Swing中,JTable如下所示:

一个JTable

JTable

最终,JTable的大部分功能超出了本教程的范围。 “ 中级摇摆 ”将对该复杂组件进行更详细的介绍。

The JTree is another complex component that is not as difficult to use as the JTable but isn't as easy as the JList either. The tricky part of working with the JTree is the required data models.

The JTree takes its functionality from the concept of a tree with branches and leaves. You might be familiar with this concept from working with Internet Explorer in Windows -- you can expand and collapse a branch to show the different leaves you can select and deselect.

You will most likely find that the tree is not as useful in an application as a table or a list, so there aren't as many helpful examples on the Internet. In fact, like the JTable, the JTree does not have any beginner-level functions. If you decide to use JTree, you will immediately be at the intermediate level and must learn the concepts that go with it. On that note, the example application does not cover the JTree, so unfortunately, neither the beginner nor the intermediate tutorial will delve into this less popular component.

However, there are times when a tree is the logical UI component for your needs. File/directory systems are one example, as in Internet Explorer, and the JTree is the best component in the case where data takes a hierarchical structure -- in other words, when the data is in the form of a tree.

In Swing, a JTree looks like this:

A JTree

JTree

Swing concepts

Layouts, models, and events, oh my!

Now that you know about most (but definitely not all) of the components you can use to make a UI, you have to actually do something with them. You can't just place them randomly on the screen and expect them to instantly work. You must place them in specific spots, react to interaction with them, update them based on this interaction, and populate them with data. More learning is necessary to fill in the gaps of your UI knowledge with the other important parts of a UI.

Therefore, let's examine:

  • Layouts: Swing includes a lot of layouts, which are classes that handle where a component is placed on the application and what should happen to them when the application is resized or components are deleted or added.
  • Events: You need to respond to the button presses, the mouse clicks, and everything else a user can do to a UI. Think about what would happen if you didn't -- users would click and nothing would change.
  • Models: For the more advanced components (Lists, Tables, Trees), and even some easier ones such as the JComboBox, models are the most efficient way to deal with the data. They remove most of the work of handling the data from the actual component itself (think back to the earlier MVC discussion) and provide a wrapper for common data object classes (such as Vector and ArrayList ).

Easy layouts

As mentioned in the last section, a layout handles the placement of components on the application for you. Your first question might be "why can't I just tell it where to go by using pixels?" Well, you can, but then you'd immediately be in trouble if the window was resized, or worse, when users changed their screen resolutions, or even when someone tried it on another OS. Layout managers take all those worries away. Not everyone uses the same settings, so layout managers work to create "relative" layouts, letting you specify how things should get resized relative to how the other components are laid out. Here's the good part: it's easier than it sounds. You simply call setLayout(yourLayout) to set up the layout manager. Subsequent calls to add() add the component to the container and let the layout manager take care of placing it where it belongs.

Numerous layouts are included in Swing nowadays; it seems there's a new one every release that serves another purpose. However, some tried-and-true layouts that have been around forever, and by forever, I mean forever -- since the first release of the Java language back in 1995. These layouts are the FlowLayout, GridLayout, and BorderLayout.

The FlowLayout lays out components from left to right. When it runs out of space, it moves down to the next line. It is the simplest layout to use, and conversely, also the least powerful layout:

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

The FlowLayout at work

FlowLayout

The GridLayout does exactly what you'd think: it lets you specify the number of rows and the number of columns and then places components in these cells as they are added:

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

The GridLayout at work

GridLayout

The BorderLayout is still a very useful layout manager, even with all the other new ones added to Swing. Even experienced UI developers use the BorderLayout often. It uses the notions of North, South, East, West, and Center to place components on the screen:

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

The BorderLayout at work

BorderLayout

GridBagLayout

While the examples from above are good for easy layouts, more advanced UIs need a more advanced layout manager. That's where the GridBagLayout comes into play. Unfortunately, it is extremely confusing and difficult to work with, and anyone who has worked with it will agree. I can't disagree either; but despite its difficulties, it's probably the best way to create a clean-looking UI with the layout managers built into Swing.

Here's my first bit of advice: In the newest versions of Eclipse, there's a built-in visual builder that automatically generates the required GridBagLayout code needed for each screen. Use it! It will save countless hours of fiddling around with the numbers to make it just right. So while I could use this slide to explain how GridBagLayout works and how to tweak it to make it work best, I'll just offer my advice to find a visual builder and generate the code. It will you save hours of work.

大事记

Finally, we get to one of the most important parts of Swing: dealing with events and reacting to interaction with the UI. Swing handles events by using the event/listener model. This model works by allowing certain classes to register for events from a component. This class that registers for events is called a listener, because it waits for events to occur from the component and then takes an action when that happens. The component itself knows how to "fire" events (that is, it knows the types of interaction it can generate and how to let the listeners know when that interaction happens). It communicates this interaction with events, classes that contain information about the interaction.

With the technical babble aside, let's look at some examples of how events work in Swing. I'll start with the simplest example, a JButton and printing out "Hello" on the console when it is pressed.

The JButton knows when it is pressed; this is handled internally, and there's no code needed to handle that. However, the listener needs to register to receive that event from the JButton so you can print out "Hello." The listener class does this by implementing the listener interface and then calling addActionListener() on the JButton:

// 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");
      }
   }

A JList works in a similar way. When someone selects something on a JList, you want to print out what object is selected to the console:

//  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());
      }
   }
   );

From these two examples, you should be able to understand how the event/listener model works in Swing. In fact, every interaction in Swing is handled this way, so by understanding this model, you can instantly understand how every event is handled in Swing and react to any possible interaction a user might throw at you.

楷模

Now, you should know about the Java Collections, a set of Java classes that handle data. These classes include an ArrayList , a HashMap , and a Set . Most applications use these classes ubiquitously as they shuttle data back and forth. However, one limitation arises when you need to use these data classes in a UI. A UI doesn't know how to display them. Think about it for a minute. If you have a JList and an ArrayList of some data object (such as a Person object), how does the JList know what to display? Does it display the first name or both the first name and the last name?

That's where the idea of a model comes in. While the term model refers to the larger scope, in this tutorial's examples I use the term UI model to describe the classes that components use to display data.

Every component that deals with a collection of data in Swing uses the concept of a model, and it is the preferable way to use and manipulate data. It clearly separates the UI work from the underlying data (think back to the MVC example). The model works by describing to the component how to display the collection of data. What do I mean by describing? Each component requires a slightly different description:

  • JComboBox requires its model to tell it what text to display as a choice and how many choices exist.
  • JSpinner requires its model to tell it what text to display, and also what the previous and next choices are.
  • JList also requires its model to tell it what text to display as a choice and how many choices exist.
  • JTable requires much more: It requires the model to tell it how many columns and rows exist, the column names, the class of each column, and what text to display in each cell.
  • JTree requires its model to tell it the root node, the parents, and the children for the entire tree.

Why do all this work, you might ask. Why do you need to separate all this functionality? Imagine this scenario: You have a complicated JTable with many columns of data, and you use this table in many different screens. If you suddenly decide to get rid of one of the columns, what would be easier, changing the code in every single JTable instance you used, or changing it in one model class you created to use with every JTable instance. Obviously, changing fewer classes is better.

Model examples

Let's take a look at how a model works by using it with an easy example, the JComboBox. In the previous slide of a JComboBox, I showed you how to add items to the data by calling setItem() . While this is acceptable for simple demonstrations, it isn't much use in a real application. After all, when there are 25 choices, and they are continually changing, do you really want to loop through them each time calling addItem() 25 times? 当然不是。

The JComboBox contains a method call setModel() that accepts an instance of the ComboBoxModel class. You should use this method instead of the addItem() method to create the data in a JComboBox.

Suppose you have an ArrayList with the alphabet as its data ("A", "B", "C", etc.):

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);
      }
   }

The great part about using a model is that you can reuse it over and over again. As an example, say the JComboBox's data needs to change from letters of the alphabet to the numbers 1 to 27. You can achieve this change in one simple line that uses the new List of data to populate the JComboBox without using additional code:

myComboBox.setModel(new MyComboModel(numberList));

Models are a beneficial feature in Swing as they provide the ability for code reuse and make dealing with data much easier. As is often the case in large-scale applications, the server-side developers create and retrieve the data and pass it to the UI developer. It's up to the UI developer to deal with this data and display it properly, and models are the tools to get this done.

Putting it all together

Example application

After all these examples, you probably want to see this stuff in action. Enough with the pretty pictures. Let's get down to a concrete example that ties together everything you've learned so far in this tutorial.

Here's the concept for the example application: a simple flight reservation system. It lets the user type in a departure and arrival city and then press a button to search. It has a fake database with flights stored in it. This database can be searched, and a table is used to display the results of the search. Once the table populates, users can select flights from the table and buy tickets by changing the number of tickets they desire and clicking a button.

It's a seemingly simple application that allows you to see all the parts of Swing in practice. This example application should answer any questions you might have had from previous sections. Before I start, let's look at the finished product:

Example application

Example Application

Step 1: Lay out the components

As I mentioned earlier, there's little need to learn complex layouts because you can use a visual editor.

Step 2: Initialize the data

The application can't work without data. Let's think about what kind of data you need in this application. First, you need a list of cities to choose from for the departure and destination cities. Then, you need a list of flights to search.

For this example, I use some fake data because the focus of the application is on Swing not on the data. You create all the data in the DataHandler class. This class manages the departure and destination cities and also handles flight search and record retrieval.

The cities are stored as simple String s. The flights however, are stored in data objects called Flight s that contain fields for the departure city, destination city, flight number, and number of available tickets.

Now, with all that red tape out of the way, let's get back to the application.

Step 3: Handling events

Let's examine the application and consider what actions must take place. First, you need to know when a user presses the Search button, so you can search the data for flights. Second, you need to know when a user selects the table of records to prevent possible errors when a user tries to buy a record with no records selected. Finally, you must be aware of when a user presses the Purchase button to send the purchasing data back to the data handler class.

Let's start with the Search button. As outlined above, you must call the addActionListener() method on the button to register for events from a button press. To keep things simple, I use the FlightReservation class to listen for all possible events. Here's the code to handle the Search button press:

String dest = getComboDest().getSelectedItem().toString();
   String depart = getComboDepart().getSelectedItem().toString();
   List l = DataHandler.searchRecords(depart, dest);
   flightModel.updateData(l);

The two cities are gathered from the combo boxes and used to search the records for the corresponding flights. Once the flights are found, they are passed to the table's table model; more on how the table models work below. But know that once the table model has the updated data, it will display the results.

Next, let's examine what happens when a user presses the Purchase button:

Object o = flightModel.getData().get(getTblFlights().getSelectedRow());
   int tixx = Integer.parseInt(getTxtNumTixx().getText());
   DataHandler.updateRecords(o, tixx);

Now, conversely, when a user presses the Purchase button, the table model figures out which flight the user selected and then passes this record and the number of tickets the user wishes to purchase to the data handler.

Finally, you need to error-check and ensure that someone doesn't try to purchase a ticket without selecting a flight in the table. The easiest way to do this is to disable the components a user would use to purchase tickets (the text field and button) and only enable them when a user selects a row:

boolean selected = getTblFlights().getSelectedRow() > -1;
   getLblNumTixx().setEnabled(selected);
   getTxtNumTixx().setEnabled(selected);
   getBtnPurchase().setEnabled(selected);

Step 4: Models

Next, let's look at the models you use to handle all the data flying back and forth in this application. By analyzing the application and going through this demo, you should clearly see that you need two models: a model for the JComboBoxes and a model for the JTable.

Let's begin with the easiest, the JComboBox's model. I won't paste the code in here because it's the same as the example a few slides ago (and in fact can be used for any of your JComboBoxes). There are some important things to note though: Remember the advantage of using models, and you'll see it in use here. Although you only have one model class, you reuse it by creating two instances of it and supplying one to each of the JComboBoxes. That way both instances can handle their own data, but of course, you only write one class to do it. Here's how you set it up:

comboModel1 = new CityComboModel(DataHandler.getCities());
   comboModel2 = new CityComboModel(DataHandler.getCities());

Let's move on to the JTable's model. This model is a bit more complicated than the JComboBox and requires a little more inspection. Let's start with your knowledge of the ComboBoxModel and see what you need to add for a JTable. Because a JTable contains data like a ComboBox, but in multiple columns, you need a lot more information from the model dealing with the column information. So, in addition to knowing the number of rows of data, you need to know the number of columns, the column names, and the value at an individual cell, instead of just the object itself. This allows you to not only display a data object, but also to display fields of a data object. In the case of this example, you don't display the Flight object; you instead display the fields of a departure city, destination city, flight number, and the number of tickets available. Below is the code you use to create the TableModel and how to set it on the JTable:

flightModel = new FlightTableModel();
   getTblFlights().setModel(flightModel);

Because of the amount of code you need to create a TableModel , I'll hold off on pasting it here, but will instead direct you to the source code of the sample application (see Related topics to download the code) to take a closer look at how it works. Also, this has really just touched on the TableModel . As I mentioned earlier, the JTable is the most difficult and complex component to work with in Swing and its parts, including the TableModel , are not any easier. That said, I will revisit the TableModel in " Intermediate Swing " in addition to other JTable functionality.

Step 5: Bells and whistles

Users have come to expect a certain amount of bells and whistles in any application, both as extra functionality and also as a way to prevent the occurrence of errors. In this example, although the basic functionality of searching for a flight and purchasing tickets works, you haven't addressed possible errors that might happen. For error-proofing, you need to add an error message when a user attempts to order more tickets than are available. How do you display errors? If you think back to the slide on the JOptionPane, Swing has a ready-made component for this type of instant feedback.

Let's look at the error condition and see what triggers the error message:

try
   {
      DataHandler.updateRecords(o, tixx);
   }
   catch (Exception ex) {
      // display error message here
   }

Now let's take care of the error message. Remember the JOptionPane and its plentiful amount of options. Let's lay out the options you want in your error message before you decide what kind of JOptionPane to create. It should be an error message and not an informative message. Use a simple title such as "Error." The detailed message consists of what the exception says. And finally, the users have made an error, so simple OK and Cancel buttons should suffice.

Here's the code to create that exact JOptionPane:

JOptionPane.showConfirmDialog(this, ex.getMessage(), "Error", 
              JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE);

And here's what it looks like:

Example error message

错误信息

And in the end ...

Hopefully, you now understand how everything described in this tutorial came together to form a basic but functional Swing application. Unfortunately, I can't squeeze every possible line of code from the example application into these slides, although I encourage you to look through the example application to see for yourself how it all developed.

Especially note how I used the models to ease the process of dealing with the data. Using some rather simple code, you can handle any kind of data that both the JTable and JComboBox can receive. Also, note the event/listener relationships -- how the components that interact all take on the event/listener relationship, meaning that interested parties (other components especially) must register for these events.

Finally, if you decide to continue to the intermediate tutorial, I will build off your knowledge of this existing flight reservation system. So, if you choose to move to the next phase, please be sure you understand how that system works in its basic form.

摘要

摘要

This tutorial introduced you to Swing and the concepts you need to know to create a basic, functional user interface. After completing this tutorial, you should have accomplished several things:

  • You should be familiar with the Swing components. You should be able to recognize the components when you see them on the screen and apply them in your own applications by using their basic functions. In addition, you should have a general understanding of when you should use the components (for example, when to use a JCheckBox vs. when to use a JRadioButton).
  • You learned how to lay out these components on the screen with layout managers. Layout managers have existed since Java first came out, and unfortunately, the most powerful layout manager is also the most difficult to use. However, visual editors (such as the one found in Eclipse) make the layout process incredibly easy by creating all the layout code automatically.
  • You learned about the event model, mainly how Swing uses the event/listener model in all of its components to allow one component to accept user interaction and pass this interaction on to other classes. These other classes register for events from the component and take appropriate action when they receive events. The event/listener model is used throughout Swing, and you should learn it in depth to better work with every Swing component.
  • You learned about data models and how they fit into the MVC architecture in Swing. Models allow components to display data without knowing anything about the data itself. They also let you reuse models, allowing multiple components that display similar data to use the same model, eliminating the need to create an original model for each instance of the component. In large-scale applications, models serve as the "translation" between server-side data objects and client-side Swing components.

It's important and vital to understand that this tutorial is not all-encompassing. It's not even meant to cover all the basics of Swing. There's just far too much to squeeze into this tutorial to give beginners a thorough introduction to Swing. I've hopefully pointed out the crucial elements, including the most commonly used components and their most commonly used functions. You should be aware that probably about twice as many components exist in Swing, and I encourage you to look through Swing documentation to cover the ones I missed. Also, I've barely touched upon the functions of most of the components; each Swing component has dozens, even up to a hundred, functions you can potentially use.

But I don't want to rain on your parade. By finishing this tutorial you've learned quite enough to build a majority of your Swing applications, and the knowledge gained from this tutorial serves as a solid foundation if you explore the other functionalities and components Swing offers.

下一步

As you know by now, this tutorial has a companion called " Intermediate Swing ," which will build upon the knowledge you've gained in this introduction with an examination the more difficult concepts you need to understand to make your application more polished and powerful. These concepts include:

  • More advanced JTable features including the table properties, more sophisticated TableModel management, the TableRenderer to change the appearance of the JTable, and how to sort the table columns.
  • Threading and how it fits into Swing. Because users cannot accept an interface that locks up when it hits the database, Swing must use separate threads for longer operations.
  • How to create custom components. If you feel limited by what Swing offers you now, I'll show you how to create components that might look or behave differently than the ones built into Swing.
  • Custom look-and-feels. I will discuss how to completely change the look and feel of an application through two methods: one creates a new custom UI look-and-feel and the other uses Synth, a skinnable look-and-feel.

翻译自: https://www.ibm.com/developerworks/java/tutorials/j-intswing/j-intswing.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值