第十一章 GUI 上

时间:2023-12-15 18:55:50

 第11章 GUI程序设计

11.1 JFC简介

JFC(Java Foundation Class) 作为CUI(Graphic User Interface)设计的基础.JFC包含AWT(Abstract Window Toolkit),Swing和Java2D

Swing相对于AWT的优点:

1:Swing不在依赖于运行时的本地组件,它完全是用Java编写的,从而解决了AWT中存在的可移植的问题

2:Swing具有可拔插的外观风格,即通过在几种预先配置好的外观风格中进行选择,可以让GUI程序显示出不同的外观风格

3:Swing采用的是MVC模式.更灵活

11.2 Swing组件的结构

1:顶层容器:JApplet,JDialog,JFrame 和JWindow及其子类

2:MVC结构

11.3:顶层容器

11.3.1:JFrame

JFrame 是最常用的一种顶层容器,它的作用是创建一个顶层的Windows窗体.JFrame的外观就像平常的Windows系统下见到的窗体,有标题,边框,菜单.

public class JFrameDemo extends JFrame

{

public static void main(String[] args)

{

JFrame frame = new JFrame();

frame.setSize(300, 300);// 设置窗体大小

frame.setLocation(400, 400);// 设置窗体显示的位置

frame.setTitle("JFrameDemo");// 设置窗体的标题frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置关闭按键的默认操作

frame.setVisible(true);// 显示窗体

}}

11.3.2 JDialog,JWindow和JApplet

JDialog是创建对话框的顶层容器类,它与JFrame的不同之处在于对话框没有最大化和最小化按钮.JWindow 也可以创建一个窗体,没有标题栏,最大化和最小化,Applet是一种能够嵌入到网页执行的Java图形程序

11.4:布局管理

Swing采用了两种布局方式:无布局管理器布局和基于布局管理器的布局.后者是Swing为了实现跨平台的动态布局效果而提出的布局方式.在设置时,我们需要调用setLayout方法,布局管理器有:FlowLayout,BorderLayout,GridLayout等多种方式.

11.4.1:无布局管理器布局

Swing提供了setLocation(),setSize(),setBounds()等布局方法,但Swing的组件中存在一个默认的布局管理器,因此这些设置方法都会失效.如果需要设置组件大小或位置,则应取消该容器的布局管理器,方法为调用setLayout方法,并将布局管理器设置为null 举例代码如下:

public class AbsoluteLayout extends JFrame

{

public static void main(String[] args)

{

AbsoluteLayout aLayout = new AbsoluteLayout();

aLayout.setVisible(true);

}

private JButton button = new JButton("JButton");// 创建button

private JTextField textField = new JTextField("JTextField");// 创建输入字符段

public AbsoluteLayout()

{

setSize(300, 300);

setLocation(400, 400);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(null);// 设置布局管理null

this.button.setLocation(20, 20);

this.button.setSize(100, 20);

add(this.button);

this.textField.setBounds(20, 50, 200, 100);// 设置输入框的位置为(20,50),宽200高100

add(this.textField);

}}

11.4.2:FlowLayout 规律是从左到右,从上到下进行放置,变化规律是:组件的大小不变,但是其相对位置会发生改变

public class FlowLayoutDemo extends JFrame

{

public static void main(String[] args)

{

FlowLayoutDemo fLayoutDemo = new FlowLayoutDemo();

fLayoutDemo.setVisible(true);

}

private JButton button1 = new JButton("first button");

private JButton button2 = new JButton("second button");

private JButton button3 = new JButton("third button");

private JButton button4 = new JButton("fourth button");

public FlowLayoutDemo()

{

setSize(300, 300);

setLocation(400, 400);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setLayout(new FlowLayout());

// 添加按键,注意设置布局方式后任何对组件进行设置的方法,都会失效

add(this.button1);

add(this.button2);

add(this.button3);

add(this.button4);

}}

11.4.3:BorderLayout 布局管理器把容器分成五个局域:North,South,East,West和Center每个局域只能放一个组件.变化规律是:组件的相对位置不变,大小发生改变.

11.4.4:GridLayout 布局管理器将整个容器划分为n行m列的网格,平均占据容器的空间,按照组件加入的顺序优先考虑按行布局,当一行布局满之后再布局下一行每行只能布局m个组件.只有昂行列不满足指定的数值时,才按行进行扩展, 举例如下

public class GirdLayoutDemo extends JFrame

{

public static void main(String[] args)

{

GirdLayoutDemo gLayoutDemo = new GirdLayoutDemo();

gLayoutDemo.setVisible(true);

}

private JButton button1 = new JButton("first button");

private JButton button2 = new JButton("second button");

private JButton button3 = new JButton("third button");

private JButton button4 = new JButton("fourth button");

public GirdLayoutDemo()

{

setSize(300, 300);

setLocation(400, 400);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// 设置格式为两行两列

setLayout(new GridLayout(2, 2));

// 添加按键,注意设置布局方式后任何对组件进行设置的方法,都会失效

add(this.button1);

add(this.button2);

add(this.button3);

add(this.button4);

}}

11.4.5:复杂界面布局

为了实现该布局需要使用容器类,例如JPanel.JPanel是一种不可见的容器,其作用是对其他容器和组件进行组织.JPanel可以通过setLayout方法设置布局方式,也可以用add方法添加Swing组件或者其他容器.JPanel只有被布局在另外的容器上才可见.如果JPanel上没有任何Swing组件,则显示空白区域.除了JPanel,JScrollPane,和JTabbedPane也是Swing中常用的容器.JScrollPane是带有滚动条的容器,如果布局组件的大小超过了容器的大小,则可以显示水平和垂直方向的滚动条.JTabbedPane是用于产生选项卡界面的容器

public class ComplexLayout extends JFrame

{

public static void main(String[] args)

{

ComplexLayout complexLayout = new ComplexLayout();

complexLayout.setVisible(true);

}

private JPanel panel1 = new JPanel();

private JPanel panel2 = new JPanel();

private JPanel panel3 = new JPanel();

private JPanel panel4 = new JPanel();

// 构造方法

public ComplexLayout()

{

setSize(500, 500);

setLocation(400, 400);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// 对panel1进行布局

layoutPanel1();

// 对panel2进行布局

layoutPanel2();

// 对panel3进行布局

layoutPanel3();

// 对panel4进行布局

layoutPanel4();

// 对顶层容器进行布局,采用的GridLayout,2行列

setLayout(new GridLayout(2, 2));

add(this.panel1);

add(this.panel2);

add(this.panel3);

add(this.panel4);

}

// Panel1布局 格式为BorderLayout

private void layoutPanel1()

{

JButton north = new JButton("north");

JButton south = new JButton("south");

JButton east = new JButton("East");

JButton west = new JButton("west");

JButton center = new JButton("Center");

this.panel1.setLayout(new BorderLayout());

this.panel1.add(north, BorderLayout.NORTH);

this.panel1.add(south, BorderLayout.SOUTH);

this.panel1.add(west, BorderLayout.WEST);

this.panel1.add(east, BorderLayout.EAST);

this.panel1.add(center, BorderLayout.CENTER);

}

// Panel2布局 格式为FlowLayout

private void layoutPanel2()

{

JButton button1 = new JButton("First button");

JButton button2 = new JButton("Second button");

JButton button3 = new JButton("Third button");

JButton button4 = new JButton("Fourth button");

this.panel2.setLayout(new FlowLayout());

this.panel2.add(button1);

this.panel2.add(button2);

this.panel2.add(button3);

this.panel2.add(button4);

}

// Panel3布局 格式为GridLayout 两行两列

private void layoutPanel3()

{

JButton button1 = new JButton("First button");

JButton button2 = new JButton("Second button");

JButton button3 = new JButton("Third button");

JButton button4 = new JButton("Fourth button");

this.panel3.setLayout(new GridLayout(2, 2));

this.panel3.add(button1);

this.panel3.add(button2);

this.panel3.add(button3);

this.panel3.add(button4);

}

private void layoutPanel4()

{

JButton button = new JButton("JButton");

JTextField textField = new JTextField("JTextField");

this.panel4.setLayout(null);

this.panel4.setLocation(20, 20);

button.setSize(100, 20);

textField.setBounds(20, 50, 200, 100);

this.panel4.add(button);

this.panel4.add(textField);

}}

11.5 事件处理

11.5.1事件处理模型

GUI程序都需要对环境中的发生的各种事件(鼠标的单击,值的改变,焦点的获取或丢失,键盘输入等)进行监控并根据事件的类型进行相应的处理.Swing采用了委托事件模型,也叫授权模型,该模型主要包含三个对象

1事件:发生在用户界面的用户交互行为所产生的一种效果

2 事件源:产生事件的对象

3 事件监听器:接受事件并对其进行处理的对象

组件作为事件源可以触发事件,一个事件源注册一个或者多个事件监听器.

委托事件模型的优点:

1:事件对象只传给注册的监听器,不会意外的被其他组件或上层容器捕获和处理

2:可以实现过滤器的功能,只监听和处理感兴趣的事件

3:实现了将事件源和事件监听器分开处理的功能

public class EventDemo extends JFrame

{

public static void main(String[] args)

{

EventDemo eventDemo = new EventDemo();

eventDemo.setVisible(true);

}

JButton button = new JButton("press me");

public EventDemo()

{

setSize(300, 300);

setLocation(400, 400);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// 设置默认事件,使用了匿名类

this.button.addActionListener(new ActionListener()

{

public void actionPerformed(ActionEvent e)

{

// 获取被单击的按钮

JButton clickButton = (JButton) e.getSource();

clickButton.setText("I have been pressed");

}

});

setLayout(new BorderLayout());

add(this.button, BorderLayout.NORTH);

}}

11.5.2:事件类

事件既是基础,又是联系各个部分的桥梁.首先,组件作为事件源产生事件,不同类型的组件会产生不同的类型的事件.事件发生后,事件被传递给对应的事件监听器实现的事件的处理方法.基类是java.util.EventObject,基类定义了getSource方法,该方法返回产生或触发事件的对象.AWTEvent定义方法getID,该方法的返回值用来区别用同一个事件类所代表的不同类型的事件.

11.5.3:事件监听器

接收事件并对事件作出相应反应的对象称为事件监听器.一个类可以实现监听器的一个或多个接口,这就需要把所实现的接口中的所定义的方法都得到实现,当对其中的方法不感兴趣时,也可以将方法体保持为空,而不给出具体的方法

事件类别/接口名字 接口中的方法  产生事件的用户操作

ComponentEvent事件

Component

Listenter 接口

    Moved

 移动组件时

    Hidden

 隐藏事件时

    Resized

 改变组建大小

    Shown

 显示组件时

ContainerEvent

事件及接口

Added

添加组件时

Removed

移动组件时

WindowEvent

窗口事件及接口

Opened

打开窗户时

Activated

激活窗口时

Dactived

窗口失去焦点时

Closing

关闭窗口时

Closed

关闭窗口后

Iconified

窗口最小化时

Deiconifed

当窗口从最小化恢复到正常大小时

MouseEvent

鼠标事件和接口

Dragged

鼠标拖动时

Moved

鼠标移动时

Action 事件和接口

Performed

单击按钮,在文本行中按回车键,双击列表框选择菜单项时

Text 文本事件和接口

textValueChanged

文本行或文本区中修改内容

Mouse鼠标事件和接口

Clicked

单击

Entered

进入

Exited

离开

Pressed

按下

Released

释放

KeyEvent键盘事件和接口

Pressed

按下键盘时

Released

释放键盘时

Typed

敲击键盘时

Focus焦点事件和接口

Gained

获得焦点时

Lost

失去焦点时

 

 

 

 

 

 

 

 

 

 

 

11.5.4:事件适配器

每个有多个方法的监听器接口都对应于一个适配器

ComponentAdapter:组件适配器

ContainerAdapter :容器适配器

FocusAdapter 焦点适配器

KeyAdapter 键盘适配器

MouseAdapter 鼠标适配器

WindowAdapter 窗口适配器

使用适配器,只需要重写需要实现的方法,不用实现无关的方法,与监听器不同的是,监听器是一个接口,而适配器是个类

public class WindowclosingDemo extends JFrame

{

public static void main(String[] args)

{

WindowclosingDemo windowclosingDemo = new WindowclosingDemo();

windowclosingDemo.setVisible(true);

}

public WindowclosingDemo()

{

setSize(300, 300);

setLocation(400, 400);

// 设置默认关闭操作作为:什么都不做

setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

addWindowListener(new WindowAdapter()

{

@Override

public void windowClosing(WindowEvent e)

{

// 询问是否关闭窗口

int answer = JOptionPane.showConfirmDialog(null, "是否关闭窗口?",

"窗口信息", JOptionPane.YES_NO_CANCEL_OPTION);

if (answer == JOptionPane.YES_OPTION)

{

System.exit(0);

}

}

});}}