java丨事件驱动程序设计学习笔记(二)

一、匿名监听器
监听器类是特意为创建一个GUI组件(例如,一个按钮)而设计的监听对象。监听器类不被其他应用程序所共享,因此,正确的做法是将它作为一个内部类定义在框架中。
可以使用匿名内部类简化内部类监听器。匿名内部类时没有名字的内部类。它进一步完成定义内部类和创建一个该类的实例。
内部类EnlargeListener:

  •  

匿名内部类:

public ControlCircle(){
//omitted
jbtEnlarge.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
    canvas.enlarge();
    }
   }
 );
}
  • 部类的语法如下:
new SuperClassName/InterfaceName(){
//implement or override methods in superclass or interface
//Other method if necessary
}

由于匿名类是一种特殊的内部类,所以,可以将它看做有以下特征的内部类:
(1)匿名内部类必须总是扩展父类或实现接口,但是它不能有显式的extends或者implements子句。
(2)匿名内部类实现父类或接口中所有的抽象方法
(3)匿名内部类总是使用它的父类的五参数构造法创建实例。如果匿名内部类实现了接口,构造方法就是Object()
(4)匿名内部类被编译为一个名为OuterClassNamen.class的类。例如,Test类中有两个匿名内部类,那么他们被编译为Testn.class的类。例如,Test类中有两个匿名内部类,那么他们被编译为Test1.class和Test$2.class
程序处理来自四个按钮的事件
AnonymousListenerDemo.java

AnnoymousListener

二、定义监听器类的另一种方式
定义监听器类有很多其他方式。例如,改写程序AnnoymousListenerDemo.java,新程序只创建一个监听器,将这个监听器注册给按钮,然后让监听器检测出事件源,即那个按钮触发了这个事件
DetectSourceDemo.java

import javax.swing.*;
import java.awt.event.*;

public class DetectSourceDemo extends JFrame {
    //创建四个按钮
    private JButton jbtNew = new JButton("New");
    private JButton jbtOpen = new JButton("Open");
    private JButton jbtSave = new JButton("Save");
    private JButton jbtPrint = new JButton("Print");

    public DetectSourceDemo() {
        //创建一个存放按钮的面板
        JPanel panel = new JPanel();
        panel.add(jbtNew);
        panel.add(jbtOpen);
        panel.add(jbtSave);
        panel.add(jbtPrint);

        add(panel);
        //创建一个监听器
        ButtonListener listener = new ButtonListener();
        //将监听器注册到事件源
        jbtNew.addActionListener(listener);
        jbtOpen.addActionListener(listener);
        jbtSave.addActionListener(listener);
        jbtPrint.addActionListener(listener);

    }
    class ButtonListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            if(e.getSource()==jbtNew)//检查事件源
                System.out.println("Process New");
            else if(e.getSource()==jbtOpen)
                System.out.println("Process Open");
            else if(e.getSource()==jbtSave)
                System.out.println("Process Save");
            else if(e.getSource()==jbtPrint)
                System.out.println("Process Print");
        }
    }
    /** Main Method */
    public static void main(String[] args) {
        JFrame frame = new DetectSourceDemo();
        frame.setTitle("DetecSourceDemo");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}
  •  

也可以自定义一个框架类实现ActionListener
FrameAsListenerDemo.java

import javax.swing.*;
import java.awt.event.*;

public class FrameAsListenerDemo extends JFrame implements ActionListener{
    //创建四个按钮
    private JButton jbtNew = new JButton("New");
    private JButton jbtOpen = new JButton("Open");
    private JButton jbtSave = new JButton("Save");
    private JButton jbtPrint = new JButton("Print");

    public FrameAsListenerDemo() {
        //创建一个存放按钮的面板
        JPanel panel = new JPanel();
        panel.add(jbtNew);
        panel.add(jbtOpen);
        panel.add(jbtSave);
        panel.add(jbtPrint);

        add(panel);
        //注册监听器到按钮
        jbtNew.addActionListener(this);
        jbtOpen.addActionListener(this);
        jbtSave.addActionListener(this);
        jbtPrint.addActionListener(this);
    }
    public void actionPerformed(ActionEvent e) {
        if(e.getSource()==jbtNew)
            System.out.println("Process New");
        else if(e.getSource()==jbtOpen)
            System.out.println("Process Open");
        else if(e.getSource()==jbtSave)
            System.out.println("Process Save");
        else if(e.getSource()==jbtPrint)
            System.out.println("Process Print");
    }
    /**Main Method */
    public static void main(String[] args) {
        JFrame frame = new FrameAsListenerDemo();
        frame.setTitle("FrameAsListenerDemo");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

FrameAsListenerDemo
这种设计并不是很好,因为它将太多的责任放在一个类中。最好能设计一个监听器类,它只负责处理事件,这样会让代码易于阅读和维护
使用内部类和匿名内部类定义监听器类已经成为事件处理程序设计的标准,因为它通常能提供清晰、干净和简洁的代码。
三、贷款计算器
(1)创建一个5行2列的GridLayou面板。将标签和文本域添加到面板中。将面板标题设置为“Enter loan amount,interset rate,and years”(请输入贷款总额、利率和年份)
(2)创建另一个带FlowLayout(FlowLayout.RIGHT)的面板,并将一个按钮添加到这个面板
(3)将第一个面板添加到框架的中央,将第二个面板添加到框架的南边
(4)创建和注册用以处理点击按钮动作事件的监听器,处理器获取关于贷款总额、利率和年数的输入,计算月偿还额和总偿还额,然后再文本域显示这些值
LoanCalculator.java

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.border.TitledBorder;

public class LoanCalculator extends JFrame{
    //为利率、年数、贷款总额、月偿还额、总偿还额创建文本框
    private JTextField jtfAnnualInterestRate = new JTextField();
    private JTextField jtfNumberOfYear = new JTextField();
    private JTextField jtfLoanAmount = new JTextField();
    private JTextField jtfMonthlyPayment = new JTextField();
    private JTextField jtfTotalPayment = new JTextField();
    //创建一个计算偿还额的按钮
    private JButton jbtComputeLoan = new JButton("Compute Payment");
    public LoanCalculator() {
        //存放标签和文本框的面板p1
        JPanel p1 = new JPanel(new GridLayout(5,2));
        p1.add(new Label("Annual Interest Rate"));
        p1.add(jtfAnnualInterestRate);
        p1.add(new Label("Number of Years"));
        p1.add(jtfNumberOfYear);
        p1.add(new Label("Loan Amount"));
        p1.add(jtfLoanAmount);
        p1.add(new Label("Monthly Payment"));
        p1.add(jtfMonthlyPayment);
        p1.add(new Label("Total Payment"));
        p1.add(jtfTotalPayment);
        p1.setBorder(new TitledBorder("Enter loan amount,interest rate,and year"));
        //存放按钮的面板p2
        JPanel p2 = new JPanel();
        p2.add(jbtComputeLoan);
        //将面板添加到框架中
        add(p1,BorderLayout.CENTER);
        add(p2,BorderLayout.SOUTH);
        //注册监听器
        jbtComputeLoan.addActionListener(new ButtonListener());

    }
    private class Loan{
        private double interest;
        private int year;
        private double loanAmount;
        public Loan(double interest,int year,double loanAmount) {
            this.interest=interest;
            this.year=year;
            this.loanAmount=loanAmount;
        }
        public double getMonthlyPayment() {
            double monthlyInterestRate = interest/1200;
            double monthlypayment = loanAmount*monthlyInterestRate/(1-(Math.pow(1/(1+monthlyInterestRate),year*12)));
            return monthlypayment;
        }
        public double getTotalPayment() {
            double totalPayment = getMonthlyPayment()*year*12;
            return totalPayment;
        }
    }
    private class ButtonListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            //从文本框中获取值
            double interest = Double.parseDouble(jtfAnnualInterestRate.getText());
            int year = Integer.parseInt(jtfNumberOfYear.getText());
            double loanAmount = Double.parseDouble(jtfLoanAmount.getText());
            //创建一个名为loan的Loan类的实例
            Loan loan = new Loan(interest,year,loanAmount);
            //显示月偿还额和总偿还额
            jtfMonthlyPayment.setText(String.format("%.2f",loan.getMonthlyPayment()));
            jtfTotalPayment.setText(String.format("%.2f", loan.getTotalPayment()));
        }
    }
    public static void main(String[] args) {
        LoanCalculator frame = new LoanCalculator();
        frame.pack();
        frame.setTitle("LoanCalculator");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
}

--------------------- 作者:一梭 来源:CSDN 原文:https://blog.csdn.net/qq_36642407/article/details/78764173?utm_source=copy 版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_41848006/article/details/82984970