微信公众号请搜索:【Codeplus】
Java通过图形用户界面(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(Component c) 方法可以移掉容器中参数c指定的组件。
(5) 注意到容器本身也是一个组件,因此可以把一个容器添加到另一个容器中实现容器的嵌套。
(6) 每当容器添加新的组件或移掉组件时,应当让容器调用validate() 方法,以保证容器中的组件能正确显示出来
➢Java提供的JFrame类的实例是一个底层容器,即通常所称的窗口。其他组件必须被添加到底层容器中,以便借助这个底层容器和操作系统进行信息交互。
➢JFrame类是Container类的间接子类。当需要一个窗口时,可使用JFrame或其子类创建一个对象。
➢窗口也是一个容器,可以向窗口添加组件。
➢需要注意的是,窗口默认地被系统添加到显示器屏幕上,因此不允许将一个窗口添加到另一个容器中。
(1) 构造方法
JFrame()//创建一个无标题的窗口。
JFrame(String s)//创建标题为s的窗口。
(2) 常用方法
public void setBounds(int a,int b,int width,int height)//设置窗口的初始位置是(a,b),即距屏幕左面a个像素、距屏幕上方b个像素;窗口的宽是width,高是height。
public void setSize(int width,int height)//设置窗口的大小。
public void setLocation(int x,int y)//设置窗口的位置,默认位置是(0,0)。
public void setVisible(boolean b)//设置窗口是否可见,窗口默认是不可见的。
public void setResizable(boolean b)//设置窗口是否可调整大小,默认可调整大小。
public void dispose()//撤消当前窗口,并释放当前窗口所使用的资源。
public void setExtendedState(int state)//设置窗口的扩展状态.
public void setDefaultCloseOperation(int operation) //该方法用来设置单击窗体右上角的关闭图标后,程序会做出怎样的处理。如:EXIT_ON_CLOSE
public void setLayout(LayoutManager mgr)//设置此容器的布局管理器
public Component add(Component comp)//将指定组件追加到此容器的尾部。
public void setMenuBar(MenuBar mb)//将此frame的菜单栏设置为指定的菜单栏。
public void validate()//使用validate方法会使容器再次布置其子组件。在修改此容器的子组件的时候(在容器中添加或移除组件,或者更改与布局相关的信息),应该调用上述方法。
下面例子使用JFrame创建了两个窗口:
import javax.swing.*;
import java.awt.*;
public class Example1 {
public static void main(String[] args) {
JFrame window1 = new JFrame("第一个窗口");
JFrame window2 = new JFrame("第二个窗口");
Container con = window1.getContentPane();
con.setBackground(Color.red);//设置窗口的颜色
window1.setBounds(60, 100, 188, 108);//设置窗口在屏幕上的位置及大小
window2.setBounds(260, 100, 188, 108);
window1.setVisible(true);
window1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//释放当前窗口
window2.setVisible(true);
window2.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类的子类JMenultem负责创建菜单项,JMenuItem类的主要方法有以下几种:
JMenuItem(String s)//构造有标题的菜单项。
JMenuItem(String text, Icon icon) //构造有标题和图标的菜单项
public void setAccelerator(KeyStroke keyStroke)//为菜单项设置快捷键
例子2在main方法中用JFrame子类创建一个有菜单的窗口:
WindowMenu.java
import javax.swing.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class WindowMenu extends JFrame {
JMenuBar menubar; //声明一个菜单条menubar
JMenu menu, subMenu; //声明两个菜单menu,subMenu
JMenuItem itemLiterature, itemCooking; //声明两个菜单项itemLiterature, itemCooking
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(JFrame.DISPOSE_ON_CLOSE);//关闭窗口后的操作
}
void init(String s) {
setTitle(s); //设置窗口的标题
menubar = new JMenuBar(); //创建一个菜单条menubar
menu = new JMenu("菜单"); //创建一个名为“菜单”的菜单
subMenu = new JMenu("体育话题"); //创建一个名为“体育话题”的菜单
//菜单上图标
//使用图标类Icon,声明一个图标,然后创建其子类ImageIcon类创建一个图标
//Icon icon = new ImageIcon("a.gif");
itemLiterature = new JMenuItem("文学话题", new ImageIcon("a.gif")); //创建菜单项itemLiterature,并带有标题和图标
itemCooking = new JMenuItem("烹饪话题", new ImageIcon("b.gif")); //创建菜单项itemCooking,并带有标题和图标
itemLiterature.setAccelerator(KeyStroke.getKeyStroke('A')); //为菜单项itemLiterature设置快捷键
itemCooking.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); //为菜单项itemCooking设置快捷键
menu.add(itemLiterature);
menu.addSeparator(); //在菜单之间增加分隔线
menu.add(itemCooking);
menu.add(subMenu);
subMenu.add(new JMenuItem("足球", new ImageIcon("c.gif")));
subMenu.add(new JMenuItem("篮球", new ImageIcon("d.gif")));
menubar.add(menu); //将菜单添加到菜单条上
setJMenuBar(menubar); //将菜单条放到窗口中
}
}
Example2.java
public class Example2 {
public static void main(String[] args) {
WindowMenu win=new WindowMenu("带菜单的窗口",20,30,200,190);
}
}
可以在命令行窗口反编译组件及时查看组件所具有的属性及常用方法,例如:
C:\>javap javax.swing.JComponent
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);
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()//该方法可以返回实际的密码
下面例子展示了一些常用组件:
import javax.swing.*;
import java.awt.*;
class ComponentInWindow extends JFrame {
JCheckBox checkBox1, checkBox2; //声明两个复选框
JRadioButton radioM, radioF; //声明两个单选框
ButtonGroup group; //声明一个按钮组
JComboBox<String> comboBox; //下拉列表
public ComponentInWindow() {
//构造方法
init(); //调用init()方法
setVisible(true); //窗口可见
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void init() {
setLayout(new FlowLayout()); //设置此容器的布局管理器
comboBox = new JComboBox<>(); //创建一个下拉列表
//创建两个复选框
checkBox1 = new JCheckBox("喜欢Java");
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);
comboBox.addItem("面向对象");
comboBox.addItem("最小生成树");
add(comboBox);
}
}
public class Example9_3 {
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 I AYER、MODAL LAYER、POPUP I AYER、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 ) 方法添加组件,然后组件c再调用setBounds(int a,int b,int width,int height)方法设置该组件在容器p中的位置和本身的大小。组件都是一个矩形结构,方法中的参数a,b是组件c的左上角在容器p中的位置坐标,即该组件距容器p左面a个像素,距容器p上方b个像素,width,height是组件c的宽和高。
下面例子是在窗口的中心位置添加一个选项卡窗格,该选项卡窗格里添加了一个网格布局面板和一个空布局面板:
Example.java
public class Example {
public static void main(String[] args) {
new ShowLayout();
}
}
ShowLayout.java
import java.awt.*;
import javax.swing.*;
public class ShowLayout extends JFrame {
PanelGridLayout panelGridLayout; //网格布局的面板
PanelNullLayout panelNull; //空布局的面板
JTabbedPane p; //选项卡窗格
ShowLayout() {
panelGridLayout = new PanelGridLayout();//创建一个网格布局的面板
panelNull = new PanelNullLayout();//创建一个空布局的面板
p = new JTabbedPane();//创建一个选项卡,用于选择哪种面板布局
p.add("网格布局的面板", panelGridLayout);//添加网格布局面板到选项卡窗格
p.add("空布局的面板", panelNull);//添加空布局的面板到选项卡窗格
add(p, BorderLayout.CENTER);//将选项卡窗格添加到ShowLayout面板
//添加按钮到大面板上
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.EXIT_ON_CLOSE);
validate();
}
}
PanelGridLayout.java
import java.awt.*;
import javax.swing.*;
public 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]);//将小的网格添加到该面板上
}
}
}
}
PanelNullLayout.java
import javax.swing.*;
public class PanelNullLayout extends JPanel {
//空白页面布局
JButton button;//“确定”按钮
JTextField text;//文本框
PanelNullLayout() {
setLayout(null); //空布局
button = new JButton("确定"); //创建“确定”按钮
text = new JTextField();//创建文本框
add(text); //将文本框添加到PanelNullLayout面板上
add(button); //将按钮添加到PanelNullLayout面板上
text.setBounds(100, 30, 90, 30); //设置文本框大小
button.setBounds(190, 30, 66, 30); //设置按钮大小
}
}
运行截图如下:
6 BoxLayout布局
Box类的类(静态)方法createHorizontalBox() 获得一个行型盒式容器;
使用Box类的类(静态)方法createVerticalBox() 获得一个列型盒式容器。
想控制盒式布局容器中组件之间的距离,需使用水平支撑组件或垂直支撑。
下面例子中有两个列型盒式容器boxVOne、boxVTwo和一个行型盒式容器boxH。将boxVOne、boxVTwo添加到boxH中并在它们之间添加了水平支撑。
Example.java
public class Example {
public static void main(String[] args) {
WindowBoxLayout win = new WindowBoxLayout();
win.setBounds(100, 100, 310, 260);
win.setTitle("嵌套盒式布局容器");
}
}
WindowBoxLayout .java
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);
}
}