通过图形用户界面(GUI:Graphics User Interface),用户和程序之间可以方便地进行交互。Java的Swing工具包中包含了许多类来支持GUI设计。如:按钮、菜单、列表、文本框等组件类,同时它还包含窗口、面板等容器类。
javax.swing包提供了功能更为强大的用来设计GUI的类。java.awt和javax.swing包中一部分类的层次关系的UML类图如图
在学习GUI编程时,必须要很好的掌握两个概念:容器类和组件类。
javax.swing包中JComponent类是java.awt包中Container类的一个直接子类、是java.awt包中Component类的一个间接子类,学习GUI编程主要是学习掌握使用Component类的一些重要的子类及其使用方法。
以下是GUI编程经常提到的基本知识点 。
(1)Java把Component类的子类或间接子类创建的对象称为一个组件.
(2)Java把Container的子类或间接子类创建的对象称为一个容器.
(3)可以向容器添加组件。Container类提供了一个public方法:add(),一个容器可以调用这个方法将组件添加到该容器中。
(4)容器调用removeAll()方法可以移掉容器中的全部组件;调用remove(Componentc)方法可以移掉容器中参数c指定的组件。
(5)注意到容器本身也是一个组件,因此可以把一个容器添加到另一个容器中实现容器套。
(6)每当容器添加新的组件或移掉组件时,应当让容器调用validate()方法,以保证容器中的组件能正确显示出来
如:
JFrame f=new JFrame();
JButton button=new JButton(“确定”)
f.add(button);
…….
f.remove(button);
Java提供的JFrame类的实例是一个底层容器,即通常所说的窗口。其他组件必须被添加到底层容器中,以便借助这个底层容器和操作系统进行信息交互。
JFrame类是Container类的间接子类。当需要一个窗口时,可使用JFrame或其子类创建一个对象。
窗口也是一个容器,可以向窗口添加组件。需要注意的是,窗口默认地被系统添加到显示器屏幕上,因此不允许将一个窗口添加到另一个容器中。
JFrame构造方法:
JFrame() 创建一个无标题的窗口。
JFrame(String s) 创建标题为s的窗口。
常用方法:
1)public void setBounds(int a,int b,int width,int height 设置窗口的初始位置是(a,b),即距屏幕左面a个像素、距屏幕上方b个像素;窗口的宽是width,高是height。
2)public void setSize(int width,int height) 设置窗口的大小。
3)public void setLocation(int x,int y) 设置窗口的位置,默认位置是(0,0)。
4)public void setVisible(boolean b) 设置窗口是否可见,窗口默认是不可见的。
5)public void setResizable(boolean b) 设置窗口是否可调整大小,默认可调整大小。
6)public void dispose() 撤消当前窗口,并释放当前窗口所使用的资源。
7)public void setExtendedState(int state) 设置窗口的扩展状态.
8)public void setDefaultCloseOperation(int operation) 该方法用来设置单击窗体右上角的关闭图标后,程序会做出怎样的处理。如:EXIT_ON_CLOSE
9)public void setLayout(LayoutManager mgr) 设置此容器的布局管理器。
10)public Component add(Component comp) 将指定组件追加到此容器的尾部。
11)public void setMenuBar(MenuBar mb) 将此 frame 的菜单栏设置为指定的菜单栏。
12)public void validate() 使用 validate 方法会使容器再次布置其子组件。在修改此容器的子组件的时候(在容器中添加或移除组件,或者更改与布局相关的信息),应该调用上述方法。
例用JFrame创建了两个窗口,程序如下:
package com.GUI;
import javax.swing.*;
import java.awt.*;
public class window1 {
public static void main(String args[]) {
JFrame win1=new JFrame("第一个窗口"); //创建窗口标题
JFrame win2=new JFrame("第二个窗口");
Container con=win1.getContentPane(); //获得JFrame的内容面板
con.setBackground(Color.yellow); //设置窗口背景色
win1.setBounds(60,100,188,108); //设置窗口在屏幕上的位置及大小
win2.setBounds(260,100,188,108);
win1.setVisible(true); //设置窗口可见
win1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//释放当前窗口
win2.setVisible(true);
win2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //退出程序
}
}
1.菜单条
JComponent类的子类JMenubar负责创建菜单条,JFrame类有一个将菜单条放置到窗口中的方法:setJMenuBar(JMenuBar bar);该方法将菜单条添加到窗口的顶端。
菜单条JMenuBar类构造方法:JMenuBar(); JMenuBar Mbar=new JMenuBar()
2.菜单
JComponent类的子类JMenu负责创建菜单。
菜单JMenu类构造方法:JMenu() ; JMenu(String s) ; JMenu m=new JMenu();
常用方法:
public void add(JMenuItem item) 向菜单增加由参数item指定的菜单项
public JMenuItem getItem(int n) 得到指定索引处的菜单选项。
public int getItemCount() 得到菜单选项的数目。
3.菜单项
JComponent类的子类JMenuItem负责创建菜单项,JMenuItem类的主要方法有以下几种:
JMenuItem(String s) 构造有标题的菜单项。
JMenuItem(String text, Icon icon) 构造有标题和图标的菜单项
public void setAccelerator(KeyStroke keyStroke)为菜单项设置快捷键
例 创建菜单
package com.GUI;
import javax.swing.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import static javax.swing.JFrame.*;
class WindowMenu extends JFrame{ //JFrame的子类
JMenuBar menubar;
JMenu menu,subMenu;
JMenuItem item1,item2;
public WindowMenu() {}
public WindowMenu(String s,int x,int y, int w,int h) {
init(s);
setLocation(x,y);
setSize(w,h);
setVisible(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
void init(String s) {
setTitle(s);
menubar=new JMenuBar();
menu= new JMenu("菜单");
subMenu= new JMenu("软件项目"); //做为子菜单添加到menu中
item1=new JMenuItem("Java话题",new ImageIcon(""));//添加图标
item2=new JMenuItem("动画话题",new ImageIcon(""));
item1.setAccelerator(KeyStroke.getKeyStroke('A')); //设置快捷键
item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_DOWN_MASK));
menu.add(item1);
menu.addSeparator();//添加横线分割符号
menu.add(item2);
menu.add(subMenu);
subMenu.add(new JMenuItem("汽车销售系统 ",new ImageIcon("")));
subMenu.add(new JMenuItem("农场信息系统 ",new ImageIcon("")));
menubar.add(menu);
setJMenuBar(menubar);
}
}
public class Menu{
public static void main(String args[]) {
WindowMenu win=new WindowMenu("带菜单的窗口",20,30,800,800);
}
}
1.文本框:由JComponent的子类JTextField创建文本框。
构造函数:JTextField( ) ; JTextField(int columns) ;
常用方法:public String getText();
public void setText(String t);
2.文本区:由JComponent的子类JTexArea创建文本区。
构造函数:JTextArea() ;JTextArea(int rows, int columns)
常用方法:public String getText();
public void setText(String t);
3.按钮:由JComponent的子类JButton类用来创建按钮。
构造函数:JButton() ; JButton(String text) ;
常用方法:public void addActionListener(ActionListener l);
4.标签:由JComponent的子类JLabel类用来创建标签。
构造函数:JLabel() ; JLabel(String text) ; JLabel(Icon image) ;
常用方法:public String getText();
public void setText(String t);
5.选择框:由JComponent的子类JCheckBox类用来创建选择框
构造函数: JCheckBox() ;JCheckBox(String text) ;
常用方法: public void addItemListener(ItemListener l)
public void addActionListener(ActionListener l)
ItemListener接口中:Object getItemSelectable()相当于getSource();
public int getStateChange();
若被选中SELECTED/DESEELCTED
6.单选按钮:由JComponent的子类JRadioButton类用来创建单项选择框。
构造函数: JRadioButton() ; JRadioButton(String text) ;
常用方法: public void addItemListener(ItemListener l)
7.下拉列表:由JComponent的子类JComboBox类用来创建下拉列表。
构造函数:JComboBox() ; JComboBox(Object[] items)
常用方法: public void addItemListener(ItemListener l)
public Object getSelectedItem();
public int getSelectedIndex()
8.密码框:由JComponent的子类JPasswordField创建密码框.
构造函数:JPasswordField() ; JPasswordField(int columns)
常用方法:public String getText();
public void setText(String t);
public void setEchoChar(char c)使用该方法重新设置回显字符.
public char[] getPassword()方法可以返回实际的密码
例
package com.GUI;
import java.awt.*;
import javax.swing.*;
class ComponentInwindow extends JFrame{
JCheckBox checkBox1, checkBox2; //复选框
JRadioButton radioM,radioF; //单选框
ButtonGroup group;
JComboBox<String> comBox; //下拉列表
public ComponentInwindow() {
init();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void init() {
setLayout(new FlowLayout());
comBox=new JComboBox<String>();
checkBox1=new JCheckBox("喜欢音乐");
checkBox2=new JCheckBox("喜欢旅游");
group = new ButtonGroup();
radioM=new JRadioButton("男");
radioF=new JRadioButton("女");
group.add(radioM);
group.add(radioF); //归组才能实现单选
add(checkBox1);
add(checkBox2);
add(radioM);
add(radioF);
comBox.addItem("音乐天地");
comBox.addItem("武术天地");
add(comBox);
}
}
public class ComponentWin{
public static void main(String args[]) {
ComponentInwindow win=new ComponentInwindow ();
win.setBounds(100,100,450,260);
win.setTitle("常用组件");
}
}
JComponent是Container的子类,因此JComponent子类创建的组件也都是容器。容器经常用来添加组件。JFrame是底层容器,本节提到的容器被习惯地称做中间容器,中间容器必须被添加到底层容器中才能发挥作用。
1.JPanel 面板:
构造方法:JPanel() ;如: JPanel p=new JPanel();
常用方法:public void add();
使用JPanel创建面板,再向这个面板添加组件,然后把这个面板添加到其它容器中。JPanel面板的默认布局是FlowLayout布局。
2.JTabbedPane选项卡窗格
可以使用JTabbedPane容器作为中间容器。当用户向JTabbedPane容器添加一个组件时,JTabbedPane容器就会自动为该组件指定对应的一个选项卡,即让一个选项卡对应一个组件。各个选项卡对应的组件层叠式放入JTabbedPane容器,当用户单击选项卡时,JTabbedPane容器将显示该选项卡对应的组件。选项卡默认地在JTabbedPane容器的顶部,从左向右依次排列。JTabbedPane容器可以使用:
add(String text,Component c);
方法将组件c添加到JTabbedPane容器中,并指定和组件c对应的选项卡的文本提示是text。
3.滚动窗格JScrollPane
滚动窗格只可以添加一个组件,可以把一个组件放到一个滚动窗格中,然后通过滚动条来观看该组件。JTextArea不自带滚动条,因此就需要把文本区放到一个滚动窗格中。例如,
JScrollPane scroll = new JScrollPane(new JTextArea());
4.拆分窗格JSplitPane
拆分窗格就是被分成两部分的容器。拆分窗格有两种类型:水平拆分和垂直拆分。水平拆分窗格用一条拆分线把窗格分成左右两部分,左面放一个组件,右面放一个组件,拆分线可以水平移动。垂直拆分窗格用一条拆分线把窗格分成上下两部分,上面放一个组件,下面放一个组件,拆分线可以垂直移动。
JSplitPane的两个常用的构造方法:
JSplitPane(int a,Component b,Component c)
参数a取JSplitPane的静态常量 HORIZONTAL_SPLIT或VERTICAL_SPLIT,以决定是水平还是垂直拆分。后两个参数决定要放置的组件。
JSplitPane(int a, boolean b,Component c,Component d)
参数a取JSplitPane的静态常量HORIZONTAL_SPLIT或VERTICAL_SPLIT,以决定是水平还是垂直拆分,参数b决定当拆分线移动时,组件是否连续变化(true是连续)。
5.JLayeredPane分层窗格
如果添加到容器中的组件经常需要处理重叠问题,就可以考虑将组件添加到分层窗格。分层窗格分成5个层,分层窗格使用
add(Jcomponent com, int layer);
添加组件com,并指定com所在的层,其中参数layer取值JLayeredPane类中的类常量:
DEFAULT_LAYER、PALETTE_LAYER、MODAL_LAYER、POPUP_LAYER、DRAG_LAYER。
DEFAULT_LAYER是最底层,添加到DEFAULT_LAYER层的组件如果和其他层的组件发生重叠时,将被其他组件遮挡。DRAG_LAYER层是最上面的层,如果分层窗格中添加了许多组件,当用户用鼠标移动一组件时,可以把该组件放到DRAG_LAYER层,这样,用户在移动组件过程中,该组件就不会被其他组件遮挡。添加到同一层上的组件,如果发生重叠,后添加的会遮挡先添加的组件。分层窗格调用public void setLayer(Component c,int layer)可以重新设置组件c所在的层,调用public int getLayer(Component c)可以获取组件c所在的层数。
当把组件添加到容器中时,希望控制组件在容器中的位置,这就需要学习布局设计的知识。
我们将分别介绍java.awt包中的FlowLayout、BorderLayout、CardLayout、GridLayout布局类和java.swing.border包中的BoxLayout布局类。
容器可以使用方法:
setLayout(布局对象);
来设置自己的布局,控制组件在容器中的位置
1.FlowLayout布局:是JPanel型容器的默认布局
1)创建布局对象 : FlowLayout flow=new FlowLayout();
2)容器con使用布局对象: con.setLayout(flow);
3)con可以使用Container类提供的add方法将组件顺序地添加到容器中
FlowLayout布局对象调用相应的方法可以重新设置布局的对齐方式等.
如: public void setAlignment(int align)
2.BorderLayout布局:
BorderLayout 布局是Window型容器的默认布局 。
使用BorderLayout布局的容器con,可以使用add方法将一个组件b添加到中心区域:con.add(b,BorderLayout.CENTER);
或 con.add(BorderLayour.CENTER,b);
3.CardLayout 布局 : 使用CardLayout的一般步骤如下:
1)创建CardLayout对象 CardLayout card=new CardLayout();
2)为容器设置布局 con.setLayout(card);
3)容器调用add(String s,Component b)将组件b加入容器,并给出了显示该组件的代号s。
4)布局对象card用CardLayout类提供的show()方法,显示容器con中组件代号为s的组件:card.show(con,s);
使用CardLayout 的容器可以容纳多个组件,但是实际上同一时刻容器只能从这些组件中选出一个来显示,就像一叠“扑克牌”每次只能显示最上面一张一样,这个被显示的组件将占据所有的容器空间,依次排序
4.GridLayout布局 :
GridLayout布局策略是把容器划分成若干行乘若干列的网格区域,组件就位于这些划分出来的小格中。 GridLayout布局编辑器的一般步骤如下:
1)创建布局对象,指定划分网格的行数m和列数n
GridLayout grid=new new GridLayout(10,8);
2)使用GridLayout布局的容器调用方法add(Component c)将组件c加入容器。
5.null布局
可以把一个容器的布局设置为null布局(空布局)。空布局容器可以准确地定位组件在容器的位置和大小。setBounds(int a,int b,int width,int height)方法是所有组件都拥有的一个方法,组件调用该方法可以设置本身的大小和在容器中的位置。
例如,p是某个容器,
p.setLayout(null);
把p的布局设置为空布局。
向空布局的容器p添加一个组件c需要两个步骤。首先,容器p使用add©方法添加组件,然后组件c再调用setBounds(int a,int b,int width,int height)方法设置该组件在容器p中的位置和本身的大小。组件都是一个矩形结构,方法中的参数a,b是组件c的左上角在容器p中的位置坐标,即该组件距容器p左面a个像素,距容器p上方b个像素,width,height是组件c的宽和高。
6.BoxLayout布局
Box类的类(静态)方法 createHorizontalBox()获得一个行型盒式容器;
使用Box类的类(静态)方法 createVerticalBox()获得一个列型盒式容器。
想控制盒式布局容器中组件之间的距离,需使用水平支撑组件或垂直支撑。
例
package com.GUI;
import java.awt.*;
import javax.swing.*;
class PanelGridLayout extends JPanel{
PanelGridLayout(){
GridLayout grid=new GridLayout(12,12); //网格布局
setLayout(grid);
Label label[][]=new Label[12][12];
for(int i=0;i<12;i++) {
for(int j=0;j<12;j++) {
label[i][j]=new Label();
if((i+j)%2==0)
label[i][j].setBackground(Color.black);
else
label[i][j].setBackground(Color.white);
add(label[i][j]);
}
}
}
}
class PanelNullLayout extends JPanel {
JButton button;
JTextField text;
PanelNullLayout() {
setLayout(null); //空布局
button = new JButton("确定");
text = new JTextField();
add(text);
add(button);
text.setBounds(100,30,90,30);
button.setBounds(190,30,66,30);
}
}
class JshowLayout extends JFrame {
PanelGridLayout pannelGrid; //网格布局的面板
PanelNullLayout panelNull ; //空布局的面板
JTabbedPane p; //选项卡窗格
JshowLayout() {
setTitle("布局练习");
pannelGrid = new PanelGridLayout();
panelNull = new PanelNullLayout();
p = new JTabbedPane();
p.add("网格布局的面板",pannelGrid);
p.add("空布局的面板",panelNull);
add(p,BorderLayout.CENTER);
add(new JButton("窗体是BorderLayout布局"),BorderLayout.NORTH);
add(new JButton("南"),BorderLayout.SOUTH);
add(new JButton("西"),BorderLayout.WEST);
add(new JButton("东"),BorderLayout.EAST);
setBounds(10,10,570,390);
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
validate();
}
}
public class ShowLayout {
public static void main(String args[]) {
new JshowLayout();
}
}
package com.GUI;
import javax.swing.*;
public class WindowBoxLayout extends JFrame {
Box boxH; //行式盒
Box boxVOne,boxVTwo; //列式盒
public WindowBoxLayout() {
setLayout(new java.awt.FlowLayout());
init();
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
void init() {
boxH =Box.createHorizontalBox();
boxVOne=Box.createVerticalBox();
boxVTwo=Box.createVerticalBox();
boxVOne.add(new JLabel("姓名:"));
boxVOne.add(new JLabel("职业:"));
boxVTwo.add(new JTextField(10));
boxVTwo.add(new JTextField(10));
boxH.add(boxVOne);
boxH.add(Box.createHorizontalStrut(10));
boxH.add(boxVTwo);
add(boxH);
}
public static void main(String args[]) {
WindowBoxLayout win=new WindowBoxLayout();
win.setBounds(100,100,310,260);
win.setTitle("嵌套盒式布局容器");
}
}