Swing
为什么需要Swing?
使用AWT已经能够实现图形界面,为什么还需要Swing?
- AWT依赖本地系统支持,在不同的系统上,外观不同.
- AWT只能实现所有平台上都有的组件,大大限制了AWT所支持的组件的数量.
- Swing完全使用100%Java实现,组件全都使用Java绘制.
- 在不同的平台上用户体验完全相同.
- 可以控制所有组件的底层代码,甚至可以重写所有组件.
- 组件数量非常多,可以实现更多功能.
- 使用MVC设计模式,组件实现更加合理和易于维护.
- 组件本身功能也更加强大.
- 实际Java的GUI应用中,大多使用Swing,很少使用AWT.
虽然AWT在实际使用中很少使用,Swing和AWT还是存在着很大的关联. - 大部分Swing组件(Jcomponent及其子类)都是AWT中Container类的子类
- Swing为AWT中几乎所有的组件都提供了相对应的组件.(通常在你熟悉的AWT组件前面加上J就是对应的Swing组件)
- Swing中可以使用AWT中的布局管理对界面进行布局管理
-
Swing中使用的时间处理方式和AWT中的事件处理方式相似
BoxLayout
出了AWT提供了Layout之外,Swing也提供了另外一种Layout.BoxLayout将组件放在单一的行或列中,和FlowLayout不同的是,它可以考虑到组件的对齐方式,最大,最小和最佳尺寸.
除此之外,开发者还可以下载第三方的Layout或者干脆自己继承Layout类设计和编写自己的Layout.
Swing基本组件
Swing为几乎所有的AWT组件提供了自己的实现,并且功能更加强大. - 可以使用setToolTipText()方法为组件设置鼠标悬停提示.
- 大部分的Swing组件(按钮、标签、菜单项等),除了可以设置文字之外,还可以设置图标(ImageIcon类).
- Swing组件可以设置一个或多个边框.其中空白边框可以用户增大组件之间的间隔,结合布局期使用往往会得到很好的效果.
- Swing组件可以设置不同的外观。每一个JComponent类都有一个对应的ComponentUI类,它为这个Jcomponent类完成诸如绘制、事件处理、计算组件大小的任务.
Swing常见组件的分类
顶层容器:
JFrame、JApplet、JDialog和Jwindow
组件容器:
Jpanel、JScrollPane、JSplitPane、JToolBar…
特殊容器(一般不会手动创建和使用):
JInternalFrame、JRootPane、JLayeredPane和JDesktopPane…
基本组件(实现主要的人机交互):
JButton、JComboBox、JList、JMenu、JSlider…
不可编辑组件:
JLabel、JProgressBar和JToolTip。
可编辑组件:
JTextField、JTextArea、JTable等。
对话框组件:
JFileChooser、JcolorChooser等。
Swing组件的关系图
Swing菜单与工具栏
Swing菜单
菜单是基本的GUI组件。
Swing菜单主要涉及的类有:
JMenuBar:主菜单栏
JPopupMenu:邮件弹出式菜单
JMenu:菜单,其下可以添加菜单项
JMenuItem:菜单项,单击将触发某功能
JCheckBoxMenuItem:带有复选框的菜单项
JRadioButtonMenuItem:带有单选框的菜单项
Jseparator:菜单的项的分割符
Swing工具栏
工具栏是除了菜单之外另外一种非常常用的GUI组件。
Swing工具栏主要涉及的类有:
JToolBar:主工具栏容器,里面可放置各种按钮和组件
JToolTip:按钮提示
JButton:工具栏上的具体按钮,通过菜单栏的add(Action)方法创建
Swing对话框
JFileChooser
让用户选择一个已有的文件或者新建一个文件
可以使用JFileChooser的showDialog、showOpenDialog或showSaveDialog()方法来打开文件对话框,但是它仅仅会返回用户选择的按钮(确认还是取消)和文件名(如果确认的话),接下来的要实现的例如存盘或者打开的功能还需要程序员自己编写
这个类提供了专门的方法用于设置可选择的文件类型,还可以指定每类文件使用的类型图标
JColorChooser
可以让用户选择所需要的颜色
通常使用这个类的静态方法showDialog()来输出标准的颜色选择对话框,其返回值就是选择的颜色
也可以通过静态方法createDialog()方式输出个性化的颜色选择对话框,例如为其添加菜单、定义其事件处理程序,这个方法的返回值就是一个对话框
JOptionPane
如果要提示一些简单的信息,在AWT中,我们需要自己继承Dialog类,并添加相应的组件。
在javax.swing包内提供了JOptionPane来显示一些简单的提示信息,或是做一些简单的选择
通过使用这个类提供的一些静态方法show×××Dialog,就可以产生四种简单的对话框
这四种对话框(除了输入对话框可以不指定父窗口)都需要提供一个父窗口组件ParentComponent
指定了父窗口后,这些对话框自动成为模式对话框
Swing中的特殊容器
JSplitPane
可以把两个组件显示在两个显示区域内,且随着区域间分隔线的拖动,区域内组件的大小也随之发生变动
它允许设置水平分割或者垂直分割;也允许设置动态拖曳功能(拖动分界线时两边组件是否会随着拖曳动态改变大小还是在拖曳结束后才改动)
我们通常先把组件放到Scroll Pane中,再把Scroll Pane放到Split Pane中。这样在每部分窗口中,都可以拖动滚动条看到组件的全部内容
具体的API请查看API文档和教材。
JTabbedPane
Tab是一种常用的界面元素,可以节省界面空间,在同一个窗口上组织多项功能,也是微软新界面体系Ribbon的核心元素之一
在基于Tab的界面中,我们可以给每项设置一个标签,每个标签下面包含为完成此功能专用的若干组件
用户要使用哪项功能,只用点击相应的标签,就可以进入相应的页面
在AWT中,可以通过CardLayout和按钮结合的方式来实现。
由于基于Tab的界面现在非常流行,在Swing中,Java提供了一种专门的容器来实现Tab界面
JLayeredPane
有关层次的组件。
JDesktopPane与JInternalFrame
如果要实现在一个主窗口中打开很多个文档,每个文档各自占用一个新的窗口,就需要使用JInternalFrame容器类
JInternalFrame的使用跟JFrame几乎一样,可以最大化、最小化、关闭窗口、加入菜单
唯一不同的是JInternalFrame不是*容器,只能作为中间容器,必须依附于顶层容器上
通常我们会将JInernalFrame加入JDesktopPane类的对象来方便管理,JDesktopPane继承自JLayeredPane,用来建立虚拟桌面。它可以显示并管理众多JInternalFrame之间的层次关系
Swing中的数值调整组件
JProgressBar
在一些软件运行时,会出现一个进度条告知目前进度如何.通过使用该组件我们可以轻松地微软件嘉善一个进度条.
JSlider
一个可以让用户通过拖动控制杆选择一个介于最大和最小值之间的数值的组件.
适合用于控制不是很精确的场景.
在界面空间比较大的时候使用比较方便,若界面空间太小,则选择不精确.
JSpinner
用于精确选择数值的组件
类似于可编辑的JComboBox,是种复合组件,由三个部分组成:向上按钮、向下按钮和一个文本编辑区
可以通过按钮来选择待选项,也可以直接在文本编辑区内输入
适用于界面空间较小或者对选择的数值控制比较精确的场景
Swing中的列表组件
MVC
Model-View-Controller Pattern(模型-视图-控制器模式),是一种常用的图形界面设计模式。
模型:图形界面系统中组件的内部数据表示。
视图:用于将组件的内部数据显示出来给用户看的类。
控制器:将模型和视图连接起来
控制用户界面上的事件
从视图上获取消息
将视图上的消息传递给模型
MVC的两种模式
JList
Swing的几乎所有组件都是根据MVC模式设计的
而JList才是使用MVC模式的经典例子。
构造函数:
public JList()
public JList(ListModel model)
public JList(Object[] data)
public JList(Vector data)
监听器:
public void addListSelectionListener( ListSelectionListener lsl)
DefaultListModel是ListModel的默认实现。
JList选择相关方法
public void clearSelection()
public int getSelectedIndex()
public int[] getSelectedIndices()
public Object getSelectedValue()
public Object[] getSelectedValues()
public void setSelectedIndex(int index)
public void setSelectedIndices(int[] indices)
public int getSelectionMode()
public void setSelectionMode(int mode)
ListSelectionModel.SINGLE_SELECTION
JComboBox
JComboxBox是下拉列表框。
和JList类似,JComboBox使用ComboBoxModel。
构造函数:
public JComboBox()
public JComboBox(Vector items)
public JComboBox(ComboBoxModel model)
监听器:
public void addActionListener(ActionListener al)
选择:
public int getSelectedIndex()
public Object getSelectedItem()
public void setSelectedItem(Object item)
public void setSelectedIndex(int index)
其他:
public void setEnabled(boolean enabled)
public void setEditable(boolean editable)
ListCellReader
ListCellRenderer用于将ListModel中的每一个数据项,渲染称为某种显示格式。
JList和JComboBox都可以使用ListCellRenderer来显示每一个列表项目。
默认的ListCellRenderer只是将ListModel中的数据显示成为一个简单的字符串。
如果需要显示格式更为复杂的列表项目,则可以自己继承并重写ListCellRenderer。
Swing中的树组件
树形结构
树形结构是一种常用的层次化显示组件。
Swing中使用JTree来表示树形结构。
JTree也完全遵循MVC模式。
低层使用TreeModel,并通过TreeCellRenderer来显示树形结构。
术语:
Root(根)
Parent(父)
Node(节点)
Branch(枝)
JTree和DefaultTreeModel
JTree用于将TreeModel中的数据以树形结构的形式显示在图形界面上。
DefaultTreeModel是一种简单的树形数据结构的实现。
DefaultTreeModel中包含有TreeNode,一般称为Root(根)
TreeNode又可以包含其他的TreeNode。
TreeModel的常用方法:
getChild(Object parent, int index)
getChildCount (Object parent)
getIndexOfChild(Object parent, Object child)
getRoot()
isLeaf(Object node)
创建JTree
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
treeModel = new DefaultTreeModel(root);
tree = new JTree(treeModel);
DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("Subroot");
treeModel.insertNodeInto(subroot, root, 0);
DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
treeModel.insertNodeInto(leaf1, subroot, 0);
DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");
treeModel.insertNodeInto(leaf2, root, 1);
JTree的选择模式
JTree的选择模式,不能在JTree上直接设置,而需要在其TreeModel上设置:
tree.getSelectionModel().setSelectionMode (
TreeSelectionModel.SINGLE_TREE_SELECTION);
JTree的选择模式:
SINGLE_TREE_SELECTION
DISCONTIGUOUS_TREE_SELECTION
CONTIGUOUS_TREE_SELECTION
监听节点事件
和其他组件一样,JTree使用监听器来监听事件
JTree的事件主要是节点被选中,使用以下方法来添加监听器:
tree.addTreeSelectionListener(TreeSelectionListener)
处理事件需要重写TreeSelectionListener中的valueChanged()方法
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
}
扩展DefaultTreeCellRender
和JList一样,JTree可以通过扩展默认的TreeCellRenderer来改变树上每个节点的显示方法。
Swing中的文本组件
JTextField和JPasswordField
JTextField使用方法和AWT中TextField类似。
JPasswordField的使用和JTextField类似,但是用户的输入都以特殊符号替代,无法看出输入的字符。
可以使用以下方法来控制特殊字符:
setEchoChar(*);
JFormattedTextField
JFormattedTextField可以验证用户的输入是否合法。
主要构造函数:
JFormattedTextField(Format)
JFormattedTextField(Formatter)
Format:
DateFormat
MessageFormat
NumberFormat
当JFormattedTextField失去焦点的时候,Format将查看用户的输入,如果可以通过Format将用户的输入转换为特定的类型,则用户输入是合法的。
可以使用isEditValid()方法来获取用户刚刚输入是否合法。