本章目标:
- 了解AWT与Swing的关系
- 掌握组件、容器、布局管理器的概念
- 了解JFrame、JPanel、JSplitPane、JTabbedPane、JScrollPane、JDesktopPane等常见容器
- 了解JLabel组件、JButton组件,并可以通过设置显示文字风格及显示图像
- 了解事件处理作用及实现机制
- 了解文本框组件、密码框组件、文本域组件的使用
- 了解单选按钮、复选框、列表框、下拉列表框等常见组件的使用及事件处理
- 了解菜单组件、文件选择组件的使用
- 了解表格的建立,并可以使用TableModel构建一个表格
在一个系统中,一个良好的人机界面无外乎是最重要的,Windows以其良好的人机操作界面在操作系统中占有绝对的统治地位,作用可见一斑。
Java中也可以完成这样的操作界面,图形用户界面(Graphical User Interface, GUI)编程主要有以下几个特征:
- 图形界面对象及其框架(图形界面对象之间的包含关系)
- 图形界面对象的布局(图形界面对象之间的位置关系)
- 图形界面对象上的事件响应(图形界面对象上的动作)
在Java的图形界面开发中有两种可使用的技术: AWT、Swing。 但是,在AWT中大量地使用了Windows的系统函数,不是使用Java开发的;而Swing是由Java来实现的用户界面类,可以在任意的系统平台上工作,但是在Swing中仍然大量使用了AWT的概念。
18.1 AWT简介
AWT(Abstract Windowing Toolkit),抽象窗口工具包,是Sun公司在发布JDK1.0时一个重要的组成部分,是Java提供用来建立和设置Java的图形用户界面的基本工具。AWT中的所有工具类都保存在java.awt包中,此包中的所有操作类可用来建立与平台无关的图形用户界面(GUI)的类,这些类又被称为组件(Components)。
在整个AWT包中提供的所有工具类主要分为以下3种:
- 组件:Component
- 容器:Container
- 布局管理器:LayoutManager
在java.awt包中所提供的组件类非常多,主要的几个类如下图所示:
18.1.1 组件
在图形界面中,用户经常会看到一个个按钮、标签、菜单等,这实际上就是一个个的组件。这些组件都会在一个窗体上显示!!
在整个AWT包中,所有的组件类(如按钮、文本框等)都是从Component和MenuComponent扩展而来的,这些类会继承这两个类的公共操作,继承关系分别如下2图所示:
(1)Component继承关系
===================================================================================
Swing中的组件: 在Swing中的所有组件类实际上也都是Component的子类,与Component不同的是,所有的组件前都加上了一个“JXx”的形式,如JButton、JLabel等。
===================================================================================
(2)MneuComponent继承关系
18.1.2 容器
所有的AWT组件都应该放到容器中,并可以设置其位置、大小等,所有的容器都是Component的子类,在AWT中包含如图所示的集中容器
18.1.3 布局管理器
使用布局管理器可以使容器中的组件按照指定的位置进行摆放。另外一个好处是,即使容器改变了大小,布局管理器也可以准确地把组件放到指定的位置,这样就可以有效地保证版面不会混乱。
在AWT中所有的布局管理器都是LayoutManager的子类。布局管理类的继承关系如下图所示:
18.2 Swing简介
AWT大量地引入了Windows函数,所以经常被称为重量级组件。在Java 2中提供了轻量级的图像界面组件 --- Swing, Swing使用Java语句实现,是以AWT平台为基础构建起来的新组件,直接使用Swing可以更加轻松地构建用户界面。
在Java中所有的Swing都保存在javax.swing包中,从包的名称中(javax)可以清楚地发现此包是一个扩展包,所有的组件是从JComponent扩展出来的。实际上是java.awt.Component的子类,如下图所示:
JComponent类几乎是所有Swing组件的公共超类。就像Component类是所有AWT组件的父类一样,所以JComponent的所有子类也都是继承了本类的全部公共操作,继承关系如下图:
从上图各个组件类的定义来看,所有的Swing组件只是比AWT组件前多增加了一个字母“J”而已。
在Swing中依然存在容器的概念,所有的容器类都是继承自AWT组件包。例如,在Swing中容器使用了JFrame、JWindow、JPanel等,这些分别是Frame、Window、Panel的子类。
在Swing中依然可以使用AWT中所提供的各个布局管理器,为组件进行统一的布局管理。要想使用布局管理器,则首先应该了解Swing中的容器及基本组件。
18.3 基本容器:JFrame
如果要使用Swing创建一个窗口,则直接使用JFrame类即可,此类事Component的子类,常用的操作方法如下:
下面使用以上方法创建一个新的窗体,如下所示:
范例:创建一个新的窗体
package org.forfan06.jframedemo;
import java.awt.Color;
import javax.swing.JFrame;
public class JFrameDemo01{
public static void main(String args[]){
JFrame jf = new JFrame("第一个Swing窗体"); //实例化窗体对象
jf.setSize(230, 80); //设置窗体大小
jf.setBackground(Color.WHITE); //设置窗体的背景颜色
jf.setLocation(300, 200); //设置窗体的显示位置
jf.setVisible(true); //让组件显示
}
}
上面程序运行之后,会直接显示出一个窗体,可以发现此窗体的标题就是在实例化JFrame时设置的标题,底色为白色,通过setSize()方法设置了其显示的大小。在代码中最重要的就是setVisible(true),如果没有这行代码,则窗体不会显示。
在这时背景颜色时使用了java.awt.Color类完成,此类 存在大量的颜色常量,直接使用这些常量就可以改变颜色。
note:上面的程序运行后,是无法退出的。虽然现在的窗体上有关闭按钮,但是,由于没有编写关于此按钮的事件处理代码。所以此按钮在上面的代码中是无法让程序退出的。
在JFrame中也可以使用Dimension类设置窗体的大小,此类封装的是组件显示宽度和高度。Dimension类的常用操作方法如下:
除了设置组件大小可以使用Dimension外,对于组件的显示位置也存在一个Point类,此类封装的是显示位置的X、Y坐标。Point类的常用操作方法如下:
范例:使用Dimension和Point类设置组件大小和显示位置
package org.forfan06.jframedemo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JFrame;
public class JFrameDemo02{
public static void main(String args[]){
JFrame jf = new JFrame("第一个Swing窗体"); //实例化窗体对象
Dimension d = new Dimension(); //实例化Dimension对象
d.setSize(230, 80); //设置大小
jf.setSize(d); //设置组件大小
jf.setBackground(Color.WHITE); //设置窗体的背景颜色
Point p = new Point(300, 200); //设置显示的坐标点
jf.setLocation(p); //设置窗体的显示位置
jf.setVisible(true); //让组件显示
}
}
上面的程序JFrameDemo01和JFrameDemo02的运行结果完全一样。
==================================================================
Question: 为什么在实例化Frame对象时不用异常处理? 在Frame类的构造方法上使用了throws关键字抛出异常,为什么在程序中没有使用try...catch语句块进行异常的捕获及处理呢?
Answer: 因为Frame类构造方法抛出的是HeadlessException异常,而,HeadlessException是RuntimeException的子类。在Java的异常处理中,只要是RuntimeException类型的异常,在程序中可以不使用try...catch进行处理也可以!!!
==================================================================
18.4 标签组件: JLabel
18.4.1认识JLabel
JLabel组件表示的是一个标签,本身也是用于显示信息的,一般情况下是不能直接更改其显示内容的。创建完的Label对象可以通过Container类中的add()方法加入到容器中,JLabel类的常用方法和常量如下图所示:
范例:使用一个标签
package org.forfan06.jframedemo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class JLabelDemo01{
public static void main(String args[]){
JFrame jf = new JFrame("Welcome to 优快云"); //实例化窗体对象
JLabel jl = new JLabel("优快云", JLabel.CENTER); //实例化JLabel对象,使用居中对齐方式
jf.add(jl);
Dimension d = new Dimension();
d.setSize(200, 70);
jf.setSize(d);
jf.setBackground(Color.WHITE);
Point p = new Point(300, 200);
jf.setLocation(p);
jf.setVisible(true);
}
}
上面程序中,实例化了一个JLabel对象,并指定内容以及对齐方式,之后将组件加入到了容器中进行显示。
如果非要在以上代码中体现容器的概念,则可以直接通过JFrame中的getContentPane()取得窗体的Container对象,并在此对象中加入组件。如下:
Container cont = jf.getContentPane(); //取得窗体的容器
cont.add(lab); //在容器中加入组件
18.4.2 更改JLabel的文字样式
以上的标签内容只是使用了默认的字体和颜色显示,如果现在要更改字体,可以直接使用Component类中定义的方法:
public void setFont(Font f)
在设置时使用了java.awt.Font类来表示字体。Font类的常用操作方法及常量如下所示:
范例:设置标签的显示字体、大小、背景颜色
package org.forfan06.jframedemo;
import java.awt.Font;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class JLabelDemo02{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云"); //实例化窗体对象
JLabel jlabel = new JLabel("优快云", JLabel.CENTER); //实例化JLabel对象,使用居中对齐
Font font = new Font("Serief", Font.ITALIC + Font.BOLD, 28);
jlabel.setFont(font); //设置标签的显示字体
jlabel.setBackground(Color.RED); //设置标签的文字颜色
jframe.add(jlabel); //向容器中加入组件
Dimension dim = new Dimension(); //实例化Dimension对象
dim.setSize(200, 70); //设置大小
jframe.setSize(dim); //设置组件大小
jframe.setBackground(Color.WHITE); //设置窗体的背景颜色
Point point = new Point(300, 200); //设置显示的坐标点
jframe.setLocation(point); //设置窗体的显示位置
jframe.setVisible(true); //让组件显示
}
}
上面程序通过JLabel标签显示后,文字设置成了红色,而且通过Font指定了其字体风格以及大小。
=================================================================================
Question:如何取得本机的全部字体? 现在的程序中使用了一种字体样式,如果想取得本机的全部字体该如何编写程序呢?
Answer: 可以使用GraphicsEnvironment类来取得本机的全部字体。 java.awt.GraphicsEnvironment可以反悔本机的全部绘图设备和全部字体的集合。该类时抽象类,要想实例化该对象,直接使用类中的getLocalGraphicsEnvironment()方法即可,之后通过getAvailableFontFamilyNames()方法就可以取得全部的可用字体。
=================================================================================
范例:取得本机中的全部可用字体
package org.forfan06.jframedemo;
import java.awt.GraphicsEnvironment;
public class GetAllFonts{
public static void main(String args[]){
//取得本地的绘图设备和字体集合
GraphicsEnvironment eq = GraphicsEnvironment.getLocalGraphicsEnvironment();
//取得全部可用的字体
String[] fontNames = eq.getAvailableFontFamilyNames();
//循环输出全部内容
for(int x = 0; x < fontNames.length; x++){
//输出每一个字体名称
System.out.println(fontNames[x]);
}
}
}
18.4.3 在JLabel中设置图片
如果现在想将一个图像设置到JLabel中也是可以的,直接使用Icon接口以及ImageIcon子类即可。 在ImageIcon中可以使用如下所示的构造方法,将图像的数据以byte数据的形式设置上去。
(1) 下面先看第一个构造方法的使用。如果要从一个图像文件爱你中取得字节数组,则必须使用InputStream类完成操作。此时假定图像的路径为D:\csdn.gif
范例:在标签上设置图像
package org.forfan06.jlabeldemo;
import java.awt.Color;
import java.awt.Font;
import java.awt.Dimension;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.Icon;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class JLabelDemo03{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
String picPath = "D:" + File.separator + "csdn.gif";
File file = new File(picPath);
InputStream input = null;
byte[] b = new byte[(int)file.length()];
try{
input = new FileInputStream(file);
input.read(b);
input.close();
}catch(Exception e){
e.printStackTrace();
}
Icon icon = new ImageIcon(b);
JLabel jlabel = null;
jlabel = new JLabel("优快云", icon, JLabel.CENTER);
Font font = new Font("Serief", Font.ITALIC + Font.BOLD, 28);
jlabel.setFont(font);
jlabel.setBackground(Color.YELLOW);
jlabel.setForeground(Color.RED);
jframe.add(jlabel);
jframe.setSize(300, 160);
jframe.setBackground(Color.WHITE);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
(2) 如果使用一个IO流进行图片读取来设置JLabel显示图形太麻烦,则可以直接将一个图片路径传递到ImageIcon的实例化中,并使用JLabel类中可以设置ImageIcon的构造方法即可。如下所示:
范例:通过图片路径来实例化ImageIcon对象
package org.forfan06.jlabeldemo;
import java.awt.Color;
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.Icon;
public class JLabelDemo04{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
String picPath = "D:" + File.separator + "csdn.gif";
Icon icon = new ImageIcon(picPath);
JLabel jlabel = null;
jlabel = new JLabel(icon, JLabel.CENTER);
jlabel.setBackground(Color.YELLOW);
jlabel.setForeground(Color.RED);
jframe.add(jlabel);
jframe.setSize(300, 160);
jframe.setBackground(Color.WHITE);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
===================================================================================
如果图像是从一个不确定输入流(如从数据库中读取BLOB字段)中而来,则要使用public ImageIcon(byte[] imageData)来实例化Icon对象;
如果图片是从文件中而来,那么就使用public ImageIcon(String filename)来实例化Icon对象。
===================================================================================
18.5 按钮组件: JButton
JButton组件表示一个普通的按钮,使用此类可以直接在窗体中增加一个按钮。JButton类的常用方法如下:
范例:建立一个普通的按钮
package org.forfan06.jbuttondemo;
import java.awt.Font;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JButton;
public class JButtonDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
JButton jbutton = new JButton("PUSH ME");
Font font = new Font("Serief", Font.BOLD, 28);
jbutton.setFont(font);
jframe.add(jbutton);
jframe.setSize(200, 70);
jframe.setBackground(Color.WHITE);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
从程序代码来看,一个按钮的显示是非常容易的,而且使用起来与JLabel没有任何区别。JButton也可以为一个按钮设置一张显示图片,与JLabel类似,直接在创建按钮对象时设置即可。(图像文件保存路径:D:\jbutton.gif)
范例:在按钮上显示图片
package org.forfan06.jbuttondemo;
import java.awt.Font;
import java.awt.Color;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.Icon;
import javax.swing.ImageIcon;
public class JButtonDemo02{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
String picPath = "D:" + File.separator + "jbutton.gif";
//实例化Icon对象方式1
File file = new File(picPath);
InputStream input = null;
byte[] b= new byte[(int)file.length()];
try{
input = new FileInputStream(file);
input.read(b);
input.close();
}catch(Exception e){
e.printStackTrace();
}
Icon icon = new ImageIcon(b);
//实例化Icon对象方式2
Icon icon2 = new ImageIcon(picPath);
JButton jbutton = new JButton(icon);
jframe.add(jbutton);
jframe.setSize(206, 78);
jframe.setBackground(Color.WHITE);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
18.6 布局管理器
了解了基本的窗体和两个组件之后,可以发现,如果不对窗体进行版面设置,则一个组件会直接充满整个窗体,所以在Java中专门提供了布局管理器来管理组件。通过布局管理器可以使用不同方式的排列组件。每当需要重新调整屏幕大小或重新绘制屏幕上任一项时,都要用到布局管理器。
在Swing中使用的所有布局管理器都可以实现LayoutManager接口,在Swing中主要使用以下5种常见的布局管理器:
- FlowLayout
- BorderLayout
- GridLayout
- CardLayout
- 绝对定位
18.6.1FlowLayout
FlowLayout属于流式布局管理器,使用此种布局方式会使所有的组件像流水一样依次进行排列。 FlowLayout类的常用方法及常量如下所示:
范例:设置FlowLayout
package org.forfan06.layoutdemo;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
public class FlowLayoutDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
jframe.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 3));
JButton jbutton = null;
for(int i = 0; i < 9; i++){
jbutton = new JButton("button - " + i);
jframe.add(jbutton);
}
jframe.setSize(280, 123);
jframe.setVisible(true);
}
}
从程序运行结果可以发现,所有的组件按照顺序依次向下排列,每个组件之间的顺序是3.之前讲解的JPanel就是采用此种布局方式,所以显示组件时顺序地向JPanel中加入。
18.6.2 BorderLayout
BorderLayout将一个窗体的版面划分成东、南、西、北、中 5个区域,可以直接将需要的组件放到这5个区域中。BorderLayout的常用方法及常量如下:
范例:设置BorderLayout
package org.forfan06.layoutdemo;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
public class BorderLayoutDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云"); //实例化窗体对象
//设置窗体中的布局管理器为BorderLayout,所有组件水平和垂直间距为3
jframe.setLayout(new BorderLayout(3, 3));
jframe.add(new JButton("东,east"), BorderLayout.EAST);
jframe.add(new JButton("西,west"), BorderLayout.WEST);
jframe.add(new JButton("南,south"), BorderLayout.SOUTH);
jframe.add(new JButton("北,north"), BorderLayout.NORTH);
jframe.add(new JButton("中,middle"), BorderLayout.CENTER);
jframe.pack(); //根据组件自动调整窗体大小
jframe.setVisible(true); //设置窗体可见
}
}
18.6.3 GridLayout
GridLayout布局管理器是以表格的形式进行管理的,在使用此布局管理器时必须设置显示的行数和列数。其常用的方法如下:
范例:设置GridLayout
package org.forfan06.layoutdemo;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
public class GridLayoutDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
//设置窗体的布局管理器为GridLayout,按3*5进行排列,水平和垂直间距均为3
jframe.setLayout(new GridLayout(3, 5, 3, 3));
JButton jbutton = null;
for(int i = 0; i < 13; i++){
jbutton = new JButton("button - " + i);
jframe.add(jbutton);
}
jframe.pack(); //根据组件自动调整窗体大小
jframe.setVisible(true);
}
}
===============================================================================在计算器的操作上可以使用GridLayout布局管理器。 在Windows的计算器程序中,可以发现有很多个按钮,此时实际上就可以通过GridLayout布局管理器摆放全部的按钮!
===============================================================================
18.6.4 CardLayout
CardLayout就是将一组组件彼此重叠地进行布局,就像一张张卡片一样,这样每次只会展现一个界面。CardLayout类的常用方法如下:
范例:设置CardLayout
package org.forfan06.layoutdemo;
import java.awt.CardLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class CardLayoutDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云"); //实例化窗体对象
Container container = jframe.getContentPane(); //取得窗体容器
CardLayout card = new CardLayout(); //定义布局管理器
jframe.setLayout(card); //设置布局管理器
container.add(new JLabel("label-A", JLabel.CENTER), "first");
container.add(new JLabel("label-B", JLabel.CENTER), "second");
container.add(new JLabel("label-C", JLabel.CENTER), "third");
container.add(new JLabel("label-D", JLabel.CENTER), "fourth");
container.add(new JLabel("label-E", JLabel.CENTER), "fifth");
jframe.pack(); //根据组件自动调整窗体大小
jframe.setVisible(true);
card.show(container, "third");
for(int = 0; i < 5; i++){
try{
Thread.sleep(3000);
}catch(InterruptedException e){
e.printStackTrace();
}
card.next(container);
}
}
}
上面程序在显示时首先会显示第3张卡片,之后循环显示每一张卡片。18.6.5 绝对定位
如果不想在窗体中指定布局管理器,也可以通过设置绝对坐标的方式完成。在Component中提供了setBounds()方法,可以定位一个组件的坐标,使用X、Y的坐标表示方式。该方法的定义如下:
public void setBounds(int x, int y, int width, int height)
在每一个组件中都存在以上方法,通过它可以设置每一个组件的具体位置。范例:使用绝对定位排版
package org.forfan06.layoutdemo;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class AbsoluteLayoutDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
jframe.setLayout(null); //使用绝对定位
JLabel title = new JLabel("www.youkuaiyun.com");
JButton enter = new JButton("进入");
JButton help = new JButton("帮助");
jframe.setSize(200, 90);
title.setBounds(45, 5, 150, 20);
enter.setBounds(10, 30, 80, 20);
help.setBounds(100, 30, 80, 20);
jframe.add(title);
jframe.add(enter);
jframe.add(help);
jframe.setVisible(true);
}
}
使用绝对定位有一点好处: 不管窗体如何改变大小,组件的位置是固定不变的;而之前的各种排版方式,当窗体改变时,组件大小也会跟着改变。18.7 其他容器
在Swing开发中,窗体部分除了可以使用JFrame表示之外,还有其他几种常见的窗体:JPanel、JSplitPane、JTabbedPane、JScrollPane、JDesktopPane、JInternalFrame等等,下面分别进行介绍。
18.7.1 JPanel
JPanel也是一种经常用到的容器之一,可以使用JPanel完成各种复杂的界面表示。在JPanel中可以加入任意的组件,之后直接将JPanel容器加入到JFrame容器中即可显示。 JPanel常用的方法如下:
范例:JPanel的基本使用
package org.forfan06.jpaneldemo;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
public class JPanelDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
JPanel jpanel = new JPanel();
jpanel.add(new JLabel("label-A"));
jpanel.add(new JLabel("label-B"));
jpanel.add(new JLabel("label-C"));
jpanel.add(new JButton("button-X"));
jpanel.add(new JButton("button-Y"));
jpanel.add(new JButton("button-Z"));
jframe.add(jpanel); //将JPanel加入到窗体
jframe.pack(); //根据组件自动调整窗体大小
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
从运行结果可以发现,所有的组件都是采用顺序的形式加入到JPanel中,最后再将JPanel加入到JFrame中。 =============================================================================
可以将多个组件加入到JPanel中实现复杂的排列。 使用JPanel并结合之前的布局管理器可以更加方便地管理组件,可以使用布局管理器对多个JPanel进行排列。而每个JPanel中也可以分别使用不同的布局管理器管理组件。这样就可以对组件进行复杂的排列
=============================================================================
18.7.2 JSplitPane
JSplitPane的主要功能是分割面板,可以将一个窗体分为两个子窗体。可以是水平排列也可以是垂直排列(子窗体间的排列关系)。
JSplitPane的主要方法及常量如下:
下面使用分割面板的方式完成上下、左右的分割程序,程序的实现思路如下图所示:
范例:实现复杂分割
package org.forfan06.jsplitpanedemo;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
public class JSplitPaneDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
Container container = jframe.getContentPane(); //得到窗体容器
JSplitPane leftSplit = null; //左右分割的SplitPane
JSplitPane tbSplit = null; //上下分割的SplitPane
leftSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JLabel("left label"), new JLabel("right label")); //设置水平分割
leftSplit.setDividerSize(3); //设置左右的分割线大小
tbSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, leftSplit, new JLabel("bottom label")); //设置垂直分割
tbSplit.setDividerSize(10); //设置上下的分割线大小
tbSplit.setOneTouchExpandable(true); //快速展开/折叠分割条
container.add(tbSplit);
jframe.setSize(230, 80);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
从运行结果中可发现,左右的分割面板的分割线长度比较小;而上下的分割面板的分割线长度大一些,并且设置了快速展开/折叠功能。18.7.3 JTabbedPane
JTabbedPane是在一个面板上设置多个选项卡供用户选择。 如果需要查看哪个方面的信息,则直接选择选项卡即可流浪。通过这种方式用户可以方便地管理自己的相关信息。
JTabbedPane类的常用方法及常量如下图所示:
范例:设置选项卡
package org.forfan06.jtabbeddemo;
import javax.swing.JTabbedPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import java.awt.Container;
import java.io.File;
public class JTabbedPaneDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
Container container = jframe.getContentPane(); //得到窗体容器
JTabbedPane tab = null;
tab = new JTabbedPane(JTabbedPane.TOP); //设置标签在顶部显示
JPanel pan1 = new JPanel();
JPanel pan2 = new JPanel();
JButton button = new JButton("button");
JLabel label = new JLabel("label");
pan1.add(button); //第一个面板加入一个按钮
pan2.add(label); //第二个面板加入一个标签
String picPath = "D:" + File.separator + "logo.gif";
tab.addTab("图片选项", new ImageIcon(picPath), pan1, "图像");
tab.addTab("文字选项", pan2); //加入两个组件
container.add(tab); //加入到容器中
jframe.setSize(230, 120);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
以上程序中建立了两个选项卡,并且将选择卡放在窗体顶部。每一个选项卡中都加入了一个JPanel面板。层次关系如下:
18.7.4 JScrollPane
在一般的图形界面中如果显示的区域不够大,往往会出现滚动条以方便用户浏览,在Swing中JScrollPane的主要功能就是为了显示的内容加入水平滚动条。JScrollPane主要由JViewport和JScrollBar两个部分组成,前者主要是显示一个矩形的区域让用户浏览;而后者主要是形成水平或垂直的滚动条,它们的关系如下图所示。
但是在开发中用户一般情况下不经常使用这两个类,因为在JScrollPane中已经为开发者提供了足够的功能。下图中列出了JScrollPane常用的方法及常量。
范例:为图片设置滚动条
package org.forfan06.jscrollpanedemo;
import java.awt.Container;
import java.io.File;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class JScrollPaneDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
Container container = jframe.getContentPane(); //得到窗体容器
String picPath = "D:" + File.separator + "csdn.gif";
Icon icon = new ImageIcon(picPath);
JPanel pan = new JPanel();
JLabel label = new JLabel(icon);
pan.add(label);
JScrollPane scrl = null;
//垂直滚动条始终显示,水平滚动条根据需要显示
scrl = new JScrollPane(pan, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
container.add(scrl);
jframe.setSize(230, 120);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
上面图片因为大小已经超过了容器本身,所以只显示了部分内容。水平滚动条是根据需要来显示的,而垂直滚动条将始终显示,用户可以自由改变窗体大小观察滚动条的显示情况。
18.7.5 JDesktopPane和JInternalFrame
在Swing中也可以完成内部窗体的显示,即在一个窗体中可以出现多个子窗体,每一个子窗体都无法超出父窗体的区域。
JDesktopPane规定了一个父窗体的基本形式,而JInternalFrame规定了各个子窗体;JInternalFrame需要加入到JDesktopPane中。这两个类的常用方法如下所示:
范例:设置内部窗体
package org.forfan06.jinternalframedemo;
import java.awt.BorderLayout;
import java.awt.Container;
import java.io.File;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class JInternalFrameDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
jframe.setLayout(new BorderLayout());
Container container = jframe.getContentPane(); //得到窗体容器
JDesktopPane desk = new JDesktopPane();
container.add(desk, BorderLayout.CENTER);
container.add(new JLabel("内部窗体"), BorderLayout.SOUTH);
JInternalFrame jif = null;
String picPath = "D:" + File.separator + "csdn.gif";
Icon icon = new ImageIcon(picPath);
JPanel pan = null;
for(int i = 0; i < 3; i++){
//实例化一个指定标题、可改变大小、可关闭、可最大化、可图标化的内部窗体
jif = new JInternalFrame("优快云-" + i, true, true, true, true);
pan = new JPanel();
pan.add(new JLabel(icon));
jif.setLocation(35 - i * 10, 35 - i * 10);
jif.add(pan);
jif.pack();
jif.setVisible(true);
desk.add(jif);
}
jframe.setSize(300, 270);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
上面代码通过循环产生了3个内部窗体,并依次设置好其在窗体中的显示位置,无论现在怎么拖拽都无法将这些内部窗体移动到窗体之外!!!
18.8 不弹起的按钮组件: JToggleButton
JButton提供了一个按钮的基本实现,但是此按钮每次单击之后都会恢复自动弹起。如果现在希望单击一个按钮后不再自动弹起,而是在第二次单击此按钮时弹起,则就必须使用JToggleButton类。JToggleButton类的常用方法如下图所示:
范例:使用JToggleButton建立按钮
package org.forfan06.jtogglebuttondemo;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
public class JToggleButtonDemo01{
public static void main(String args[]){
JFrame jframe = new JFrame("Welcome to 优快云");
JToggleButton button1 = new JToggleButton("已选中", true);
JToggleButton button2 = new JToggleButton("未选中");
JToggleButton button3 = new JToggleButton("按我");
jframe.setLayout(new GridLayout(3, 1));
jframe.add(button1);
jframe.add(button2);
jframe.add(button3);
jframe.setSize(200, 100);
jframe.setLocation(300, 200);
jframe.setVisible(true);
}
}
程序中的3个按钮,button1因为已经设置为已选中状态,所以程序刚运行就是按下的状态,之后又设置了两个没有被默认选中的按钮,当每次单击之后按钮不会自动弹起。