事件驱动程序设计学习笔记
来源:互联网 发布:kenzo知乎 编辑:程序博客网 时间:2024/05/23 01:19
如果希望可以编写一个GUI程序提示用户输入贷款总额,年利率,年数,然后点击OK按钮获取月偿还额和总偿还额。则必须使用时间驱动程序设计来编写代码。
事件和事件源
能创建一个事件并能触发该事件的组件成为源对象或是源组件。如按钮是按钮点击动作事件的源对象。一个事件是一个事件类的实例化。事件的根类是java.util.EventObject。
除了ListSelectionEvent和ChangeEvent之外所有的事件类都包括在java.awt.event包中,ListSelectionEvent和ChangeEvent在java.swing.event包中。AWT事件本来就是为了AWT组件设计的,但是很多Swing组件都会用到它们。
监听器,注册,处理事件
Java使用一种基于委托的模型来处理事件:源对象触发一个事件,对此事件感兴趣的对象会处理它。对此事件感兴趣的对象成为监听器(listener)。一个对象要成为源对象的监听器需要具备两个条件:
1. 监听器对象的类必须是相应的事件监听器接口的实例,以确保监听器有处理这个时间的正确方法。
2. 监听器对象必须有源对象注册。
现在我们可以编写一个程序,使用两个按钮控制一个圆的大小。代码如下
import java.util.*;import javax.swing.*;import javax.swing.border.Border;import java.io.*;import java.awt.*;import java.awt.event.*;class ArcPanel extends JPanel {private int radius = 5;protected void paintComponent(Graphics g) {super.paintComponent(g);g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, 2 * radius, 2 * radius);}public void enlarge() {radius += 5;repaint();}public void shrink() {radius -= 5;repaint();}}public class Main extends JFrame {private JButton jbtEnlarge = new JButton("Enlarge");private JButton jbtShrink = new JButton("Shrink");private ArcPanel canvas = new ArcPanel();public Main() {JPanel panel = new JPanel();panel.add(jbtEnlarge);panel.add(jbtShrink);this.add(canvas, BorderLayout.CENTER);this.add(panel, BorderLayout.SOUTH);jbtEnlarge.addActionListener(new EnlargeListener());jbtShrink.addActionListener(new ShrinkListener());}class EnlargeListener implements ActionListener {public void actionPerformed(ActionEvent e) {canvas.enlarge();}}class ShrinkListener implements ActionListener {public void actionPerformed(ActionEvent e) {canvas.shrink();}}public static void main(String[] args) {Main frame = new Main();frame.setTitle("Main");frame.setSize(250, 300);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}}
由上面的代码显示,我将EnlargeListener和ShrinListener定义成了内部类,通常,如果一个类只是被外部类使用,就将该类定义为内部类。一个内部类有如下特征:
1. 一个内部类被编译成一个名为OutClass$InnerClass.class的类。
2. 内部类可以引用定义在它嵌套外部类中的数据和方法,所以,不需要将外部类对象的引用传递给内部类的构造方法,因此,内部类可以使程序更加简单和简洁。
3. 使用可见修饰符定义内部类时,遵从应用与在类成员上一样的可见性原则。
4. 可以讲内部类定义为static。一个static内部类可以使用外部类的名字访问。一个static类是不能访问外部类的非静态成员的。
5. 内部类对象经常在外部类中创建。但是也可以从另一个类中创建一个内部类的对象,如果该内部类是非静态的,必须先创建一个外部类的实例,然后使用下面的语法创建以一个内部类对象:
OutClass.InnerClassinnerObject = outObject.new InnerClass();
6. 如果内部类是静态的,那么使用下面的语法为它创建一个对象:
OutClass.InnerClassinnObject = new OutClass.InnerClass();
匿名内部类:
我们可以把上面的监听器重新写,代码如下:
jbtEnlarge.addActionListener(new ActionListener(){ public void actionPerformed(ActionListen e){ canvas.enlarge();}})
匿名内部类:
1. 匿名内部类必须总是扩展父类或实现接口,但是它不能有显示的extends或者implements子句。
2. 匿名类必须实现父类或者接口内的所有方法。
3. 匿名内部类总是使用它的父类的无参构造方法来创建实例,如果匿名内部类实现了接口,构造方法就是Object();
4. 匿名内部类被编译为一个名为OuterClassName$n.class的类。
定义监听器的另外一种方式
话不多说,贴上代码:
import java.util.*;import javax.swing.*;import javax.swing.border.Border;import java.io.*;import java.awt.*;import java.awt.event.*;public class Main extends JFrame {private JButton jbtEnlarge = new JButton("Enlarge");private JButton jbtShrink = new JButton("Shrink");private ArcPanel canvas = new ArcPanel();private ButtonListener listener = new ButtonListener();public Main() {JPanel panel = new JPanel();panel.add(jbtEnlarge);panel.add(jbtShrink);this.add(canvas, BorderLayout.CENTER);this.add(panel, BorderLayout.SOUTH);jbtEnlarge.addActionListener(listener);jbtShrink.addActionListener(listener);}class ButtonListener implements ActionListener{public void actionPerformed(ActionEvent e){if(e.getSource() == jbtEnlarge)canvas.enlarge();else if(e.getSource() == jbtShrink)canvas.shrink();}}class ArcPanel extends JPanel {private int radius = 5;protected void paintComponent(Graphics g) {super.paintComponent(g);g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, 2 * radius, 2 * radius);}public void enlarge() {radius += 5;repaint();}public void shrink() {radius -= 5;repaint();}}public static void main(String[] args) {Main frame = new Main();frame.setTitle("Main");frame.setSize(250, 300);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}}
如上代码所示,我们只定义了一个监听器 listener。我们可以通过getSource()方法获取我们鼠标点击的按钮,这样可以减少类的定义从而简化代码。
实例:贷款计算器
要求:
(1) 创建一个如图所示的用户接口
(2) 创建一个5行2列的GridLayout面板,添加文本和标签
(3) 创建一个FlowLayout面板,并添加一个按钮
(4) 将两个面板添加到框架中
(5) 处理事件
代码如下:
import java.util.*;import javax.swing.*;import javax.swing.border.Border;import javax.swing.border.TitledBorder;import java.io.*;import java.awt.*;import java.awt.event.*;public class Main extends JFrame {private JTextField jtfAnnualInterestRate = new JTextField("please type rate here");private JTextField jtfNumberOfYears = new JTextField("please type year here");private JTextField jtfLoanAmount = new JTextField("please type loanAmount here");private JTextField jtfMonthlyPayment = new JTextField("output");private JTextField jtfTotalPayment = new JTextField("output");private JButton jbtComputeLoan = new JButton("Compute Payment");public class ButtonListener implements ActionListener{public void actionPerformed(ActionEvent e) {double interest = Double.parseDouble(jtfAnnualInterestRate.getText());int year = Integer.parseInt(jtfNumberOfYears.getText());double loanAmount = Double.parseDouble(jtfLoanAmount.getText()); // loan(interest,year,loanAmount);jtfMonthlyPayment.setText(String.format("%.2f", loanAmount));//这里只是一个替代。。。。。jtfTotalPayment.setText(String.format("%.2f", loanAmount));// 这里只是一个替代。。。。。}}public Main(){JPanel p1 = new JPanel(new GridLayout(5,2));p1.add(new JLabel("Annual Interest Rate"));p1.add(jtfAnnualInterestRate);p1.add(new JLabel("Number of Years"));p1.add(jtfNumberOfYears);p1.add(new JLabel("Loan Amount"));p1.add(jtfLoanAmount);p1.add(new JLabel("Monthly Payment"));p1.add(jtfMonthlyPayment);p1.add(new JLabel("Total Payment"));p1.add(jtfTotalPayment);p1.setBorder(new TitledBorder("Enter loan amount,interest rate,and year"));JPanel p2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));p2.add(jbtComputeLoan);add(p1,BorderLayout.CENTER);add(p2,BorderLayout.SOUTH);jbtComputeLoan.addActionListener(new ButtonListener());}public static void main(String[] args) {Main frame = new Main();frame.pack();frame.setTitle("LoanCalculator");frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}}
Loan类的实现我已经实现过了,可是文件丢失了,然后我又不想再写一遍。。。。。
实例学习:使用鼠标在面板上拖动消息(用到方便适配器)
上代码:
import java.util.*;import java.util.Timer;import javax.swing.*;import javax.swing.border.Border;import javax.swing.border.TitledBorder;import java.io.*;import java.awt.*;import java.awt.event.*;public class Main extends JFrame {static class MovableMessagePanel extends JPanel {private String s = "Welcomea To Java!";private int x = 20;private int y = 20;public MovableMessagePanel(String s) {this.s = s;addMouseMotionListener(new MouseAdapter() {public void mouseDragged(MouseEvent e) {x = e.getX();y = e.getY();repaint();}});}protected void paintComponent(Graphics g){super.paintComponent(g);g.drawString(s, x, y);}}public Main() {MovableMessagePanel p =new MovableMessagePanel("Hello Java!");setLayout(new BorderLayout());add(p);}public static void main(String[] args) {Main frame = new Main();frame.setTitle("MoveMessageDemo");frame.setSize(200,100);frame.setLocationRelativeTo(null);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}}
使用MouseMotionAdapter覆盖mouseDragged方法,如果内部类实现了MouseMotionListener接口,即使监听器并不关心某些事件,也必须要实现所有的处理器。
本章小结:
1. 事件类的根类是java.util.EventObject。EventObject的子类处理各种特殊类型的时间,例如动作事件,窗口时间,组件事件,鼠标事件和按键事件。可以使用EventObject类中的getSource()实例方法判断事件的源对象。如果一个组件能够触发整个事件,那么它的所有子类都能触发同类型的事件。
2. 监听器对象的类必须时间相应的时间监听器接口。Java语言为每种事件类提供监听器接口。XEvent的监听器接口通常命名为XListener,但是MouseMotionListener除外。例如,ActionEvent对应的监听器接口是ActionListener,每个ActionEvent的监听器都应该实现ActionListener接口,监听器接口包含成为处理器的处理事件的方法。
3. 监听器对象必须由源对象注册。注册方法依赖于事件的类型。对ActionEvent来讲,注册方法是addActionListener。一般来说XEvent的方法命名为addXListener。
4. 内部类或者是嵌套类是定义在另一个类中的类。内部类可以应用定义在它嵌套的外部类中的数据和方法。所以,不需要将外部类的引用传递给内部类的构造方法。
5. 方便适配器能够提供监听器接口中所有方法的默认实现类的支持类。Java为每一个AWT监听器接口提供多个处理器的方便监听器适配器,XListenerde 方便监听器适配器命名为Xadapter。。
6. 一个源对象可以触发几种类型的事件。对每种事件,源对象维护一个注册的监听器列表,通过调用监听器对象的处理器,通知所有已经注册的监听器取处理事件。
7. 在一个组件上点击,释放,移动或拖动鼠标就会触发鼠标事件。鼠标事件对象捕获事件,例如和事件相关的点击次数和鼠标点的位置(x,y坐标)
8. Java提供两个处理鼠标事件的监听器接口,MouseListener和MouseMotionListner来处理事件,实现MouseListener接口来监听注入按下,释放,点击,输入或退出鼠标等动作,实现MouseMotionListener接口来监听注入移动或拖动鼠标的动作。
9. KeyEvent对象描述事件的性质(即按下,释放或敲击一个键)以及相对应的键值
10. 当按下按键是就会调用keyPressed处理器,当释放按键时会调用keyReleased处理器,而当敲入一个统一码字符键是,就会调用keyTyped处理器。如果某个按键没有统一码(如功能键,修改键,动作键和控制键),则不会调用keyTyped处理器。
可以使用Timer类控制Java的动画。定时器以固定频率触发ActionEvent。监听器通过更新画面来模拟动画。- 事件驱动程序设计学习笔记
- Java学习笔记----事件驱动程序设计
- java丨事件驱动程序设计学习笔记(一)
- java丨事件驱动程序设计学习笔记(二)
- 字符驱动程序设计学习笔记4-1
- 字符驱动程序设计学习笔记4-2
- 事件驱动程序设计
- [Java]事件驱动程序设计
- 事件驱动程序设计-窗口事件
- 按键驱动程序设计笔记
- 按键驱动程序设计笔记
- 我想学习驱动程序设计
- Linux_USB驱动程序设计学习
- ok6410学习笔记(18.linux串口驱动程序设计)
- ok6410学习笔记(19.块设备驱动程序设计)
- ok6410学习笔记(18.linux串口驱动程序设计)
- 驱动程序学习笔记
- 第16章 事件驱动程序设计
- LeetCode 228 Summary Ranges
- java与.net des加解密 方法解析
- Android Intent的使用
- 《机器学习实战》 自制勘误表 中文版第一版2015年9月第11次印刷版
- Python:字符串分割
- 事件驱动程序设计学习笔记
- 启承转合——沟通管理之我见
- Oracle 基础
- get方式提交中文到服务器显示乱码问题
- Android Handler 小结
- 接收前台返回的Json格式参数
- 魅族魅蓝真机调试不能识别设备
- apache 开启gzip压缩 (gzip 等同于mod_deflate )
- test again