java swing开发窗体程序开发(二)事件(Action,Item,Document)

本文详细介绍了 Java Swing 中的事件处理机制,包括 ActionEvent、ItemEvent 和 DocumentEvent 三种事件类型及其应用场景。通过实例展示了如何实现事件监听及响应。

整个窗体程序的运行模式是:事件处理模式。需要理解这个模式,要了解3个基本概念
事件源:即产生这个事件的组件
监视器:即监视这个组件产生事件,即实现事件接口的类的对象
处理事件的接口:即这是一个类,实现了该种事件对应的接口,接口中必须实现一指定函数,当事件发生时,就会调用这个函数

进一步流程就是
1确定该组件的事件类型-2创建一个类实现该组件的事件类型对应的接口,这个类的对象就是监视器-3组件通过addXXXListen(监视器对象)将该
监视器添加-4在窗体上操作,产生对应的事件时将会执行那个监视器类中的对应函数【利用接口回调】。

需要注意的一点,并不是所有的组件都是同样事件类型,事件类型有很多种,有些组件是相同的,有些是不同的。

(一)ActionEvent事件

该事件的触发通常是 文本框,按钮,菜单项,密码框和单选按钮触发的。按钮和菜单项可以在点击时触发,文本框密码框之类的可以在回车时触发。
其要求的监视器类型接口是ActionListener,即需要有一个自定的类实现ActionListener接口,该接口的核心函数actionPerformed(ActionEvent e)需要实现该函数
组件对象通过addActionListener(ActionListener listener)将实现了ActionListener接口的类的对象传入。一但事件发生,就可以通过接口回调的方式调用这个actionPerformed函数。
需留意:这个ActionEvent类型的参数e,可以用他来获得到产生该事件时传来的数据,比如输入文本后回车,e可以获得文本的内容
通过e.getActionCommond()函数来获得(×稍后讲解他的局限性和另外的方法获得输入的内容)

以下是一个小案例,来展示从界面输入的值回车后,打印在控制台并输出他的长度

 public class InputListener implements ActionListener {
     /**
      * 实现该接口的方法
      * @param e
      */
     public void actionPerformed(ActionEvent e)
     {
         //通过ActionEvent对象来获得输入
         String str=e.getActionCommand();
         System.out.println("输入了"+str+"长度为:"+str.length());
     }
 }
 /**
  * 一个简单的窗口
  */
 public class SimpleForm extends JFrame {
     private JTextField textField;//一个输入框
     private InputListener inputListener;//一个实现了ActionListener接口的监视器
     public SimpleForm()
     {
         //设置GUI
         setLayout(new FlowLayout());
         textField=new JTextField(10);
         add(textField);
         setBounds(100,100,310,260);
         setVisible(true);
         setDefaultCloseOperation(DISPOSE_ON_CLOSE);
         //设置监听器
         inputListener=new InputListener();//监听器初始化
         textField.addActionListener(inputListener);//为该组件添加监视器
 
     }
 
 }
 //启动类
 public class Main {
     public static void  main(String []args)
     {
         SimpleForm form=new SimpleForm();
     }
 }

刚刚提到过,可以ActionEvent获得输入,其实这种获取局限性很高,因为他只能获取一个输入,当有多个输入框,且使用一个按钮,按钮点击时获得所有输入框的值
这种方式就不适用了。以下提供下面一种解决方式

前提:需要保证这个实现接口的类能够拿到组件的引用,通过组件自己的get方法拿到组件中的值
改写如下

/**
 * 一个简单的窗口
 */
public class SimpleForm extends JFrame {
    private JTextField textField;//一个输入框
    private InputListener inputListener;//一个实现了ActionListener接口的监视器
    public SimpleForm()
    {
        //设置GUI
        setLayout(new FlowLayout());
        textField=new JTextField(10);
        add(textField);
        setBounds(100,100,310,260);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        //设置监听器
        inputListener=new InputListener();//监听器初始化
        textField.addActionListener(inputListener);//为该组件添加监视器
        inputListener.setJTextField(textField);//【法2】通过引用来拿到组件中的值
    }

}
public class InputListener implements ActionListener {
    //通过拿到组件引用获得里面的值的方法
    private JTextField textField;
    public void setJTextField(JTextField textField)
    {
        this.textField=textField;
    }


    /**
     * 实现该接口的方法
     * @param e
     */
    public void actionPerformed(ActionEvent e)
    {
        //通过ActionEvent对象来获得输入
        //String str=e.getActionCommand();
        //System.out.println("输入了"+str+"长度为:"+str.length());

        //【法2】不使用ActionEvent对象来获得组件的值,通过组件引用来拿到值
        String str=textField.getText();
        System.out.println("输入了"+str+"长度为:"+str.length());
    }
}

效果如下-输入完后按回车
在这里插入图片描述
当然,这种效果并不直观,因为用户交互始终是在窗体上,且实际应用发布后不会有控制台,所以需要把结果也显示在窗体上。对以上程序进行了改进

public class InteractorListener implements ActionListener {
    private JTextField textField;
    private JTextArea textArea;
    public void setJTextField(JTextField textField)
    {
        this.textField=textField;

    }
    public void setJTextArea(JTextArea textArea)
    {
        this.textArea=textArea;
    }

    /**
     * 实现接口函数
     */
    public void actionPerformed(ActionEvent e)
    {
        String input=textField.getText();//获取到文本框的输入
        textArea.append("输入的是"+input+"长度为"+input.length()+"\n");//再将该输入作用到窗口中的组件
    }
}
public class SimpleForm extends JFrame {
    private JTextField inputTextField;
    private JTextArea resultTextArea;
    private JButton executeBtn;
    private InteractorListener listener;
    public SimpleForm()
    {
        //GUI部分
        setLayout(new FlowLayout());
        inputTextField=new JTextField(10);
        resultTextArea=new JTextArea(9,30);
        executeBtn=new JButton("执行");
        add(new JScrollPane(resultTextArea));//将多行文本输入放入滚条面板,把滚条面板加入该面板
        add(inputTextField);
        add(executeBtn);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setTitle("交互演示");
        setBounds(100,100,460,360);
        //设置监听器
        listener=new InteractorListener();//实例化监听器
        listener.setJTextField(inputTextField);//设置获取值组件
        listener.setJTextArea(resultTextArea);//设置输出值的组件
        inputTextField.addActionListener(listener);//为输入框事件源添加监听器:即代表回车后会触发事件
        executeBtn.addActionListener(listener);//为按钮事件源添加监听器:即代表按钮点击后会触发事件
    }
}
public class Main {
    public static void main(String []args)
    {
        SimpleForm form=new SimpleForm();
    }
}

效果如下

在这里插入图片描述
ActionEvent 变量的用处还是有的。当对于菜单项点击时使用,就是一大便利之处。
为多个菜单项添加同一个ActionEvent监听器对象,然后这个ActionEvent监听器的actionFormed函数中,通过e.getActionComond()来区分到底点击的是哪个菜单项,然后执行对应的操作。此时就是这种方式的优点,如果不这么做,通过获取组件引用的方式,就会产生多个(个数为菜单项的个数)监听器。更加麻烦
使用这种方式有一个前提,需要对JMenuItem 对象,即菜单项对象进行设置ActiionComond,即调用setActionComond(string str)后面有一个排序单词的窗体程序就展示了这个效果

(二)ItemEvent事件

该事件通常是由选择框(checkbox复选框,radioBox单选框)和下拉菜单触发的,选择框共有两种状态,即选中和未选中,当选中状态发生改变就会触发
ItemEvent事件,其要求的监视器接口类型为ItemListener,即需要有一个类来实现ItemListener接口,并实现其核心函数itemStateChanges(ItemEvent e).
组件通过addItemListener(ItemListener listener),传入实现了这个ItemListener接口的类的对象,一但事件发生,将会通过接口回调的方式调用这个addItemListener函数


以下用这个ItemEvent做了一个简易计算器
这个案例涉及到两个监听器

public class CaculateListener implements ActionListener {
    private String fuhao;
    public void setFuhao(String fuhao)
    {
        this.fuhao=fuhao;
    }
    private JTextField num1;
    private JTextField num2;
    private JButton caculateBtn;
    private JTextArea resultArea;

    public void setNum1(JTextField num1) {
        this.num1 = num1;
    }

    public void setNum2(JTextField num2) {
        this.num2 = num2;
    }

    public void setCaculateBtn(JButton caculateBtn) {
        this.caculateBtn = caculateBtn;
    }

    public void setResultArea(JTextArea resultArea) {
        this.resultArea = resultArea;
    }

    /**
     * 实现该接口的函数
     * @param actionEvent
     */
    public void actionPerformed(ActionEvent actionEvent)
    {
        try {
            double d1 = Double.parseDouble(num1.getText());
            double d2=Double.parseDouble(num2.getText());
            double res=0;
            if(fuhao.equals("+"))
            {
                res=d1+d2;
            }else if(fuhao.equals("-"))
            {
                res=d1-d2;
            }else if(fuhao.equals("*"))
            {
                res=d1*d2;
            }else if(fuhao.equals("/"))
            {
                res=d1/d2;
            }
            resultArea.append(d1+fuhao+d2+"结果为"+res+"\n");
        }catch (Exception e)
        {
            System.out.println("发生运算错误,异常信息为:"+e);
        }
    }
}

public class FuhaoListener implements ItemListener {
    private JComboBox fuhaoBox;//获得符号下拉菜单的引用,以便获取其中选到的值
    public void setFuhaoBox(JComboBox fuhaoBox)
    {
        this.fuhaoBox=fuhaoBox;
    }
    private CaculateListener caculateListener;//获得另一个监听器的引用,因为需要吧选则的运算符传过去
    public void setCaculateListener(CaculateListener listener)
    {
        this.caculateListener=listener;
    }


    /**
     * 实现函数
     * @param e
     */
    public void itemStateChanged(ItemEvent e)
    {
        System.out.println("符号设置了");
        String fuhao=fuhaoBox.getSelectedItem().toString();
        //要把这个符号设置给另一个Listener,让他知道运算符是啥
        caculateListener.setFuhao(fuhao);
    }

}
public class CaculatorForm extends JFrame {
    private JTextField inputNum1;//第一个操作数
    private JTextField inputNum2;//第二个操作数
    private JComboBox choiceFuhao;//操作符
    private JButton caculateBtn;//进行计算
    private JTextArea resTextArea;//结果显示区
    //监视器定义
    private CaculateListener caculateListener;
    private FuhaoListener fuhaoListener;

    public CaculatorForm()
    {
        //GUI部分
        setLayout(new FlowLayout());
        inputNum1=new JTextField(10);
        inputNum2=new JTextField(10);
        choiceFuhao=new JComboBox();
        String []fuhaos={"+","-","*","/"};
        for(String temp:fuhaos)
        {
            choiceFuhao.addItem(temp);
        }
        caculateBtn=new JButton("计算");
        resTextArea=new JTextArea(9,30);
        add(inputNum1);
        add(inputNum2);
        add(choiceFuhao);
        add(caculateBtn);
        add(resTextArea);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setBounds(100,100,390,360);
        setTitle("计算器");


        //设置监听器
        caculateListener=new CaculateListener();
        fuhaoListener=new FuhaoListener();
        //设置组件
        fuhaoListener.setCaculateListener(caculateListener);//最重要的一步,因为该窗体涉及到两个监听器,且之间有通讯
        caculateListener.setNum1(inputNum1);
        caculateListener.setNum2(inputNum2);
        caculateListener.setCaculateBtn(caculateBtn);
        caculateListener.setResultArea(resTextArea);
        fuhaoListener.setFuhaoBox(choiceFuhao);

        //添加监听
        choiceFuhao.addItemListener(fuhaoListener);
        caculateBtn.addActionListener(caculateListener);
    }

}

public class Main {
    public static void main(String[] args)
    {
        CaculatorForm form=new CaculatorForm();
    }
}

效果如下
在这里插入图片描述

(三)DocumentEvent事件

该事件的触发只有一个组件,即文本区组件JTextArea。只要当文本框中的内容发生改变时就会触发。其要求的监视器的接口类型为DocumentListener
即需要有一个类来实现DocumentListener接口,并实现该接口中的核心函数,该接口中有3个需要实现的函数:
1:void changedUpdate(DocumentEvent e)
2:void removeUpdate(DocumentEvent e)
3:void insertUpdate(DocumentEvent e)

由于文档变化一共就有以上3种可能,被替换,被移除,新插入。发生了对应的事件,就会执行其中对应的函数。
以下是一个demo,实时对左边输入的单词进行排序

public class EditorListener implements DocumentListener {
    private JTextArea inputArea;
    private JTextArea outputArea;


    public void setInputArea(JTextArea inputArea) {
        this.inputArea = inputArea;
    }

    public void setOutputArea(JTextArea outputArea) {
        this.outputArea = outputArea;
    }

    //实现该接口的3个核心函数
    //该案例的需求,只要变动了就进行排序,所以这3个函数执行的内容都是相同的,为了避免代码重复可以
    public void insertUpdate(DocumentEvent e)
    {
        sort();
    }
    public void removeUpdate(DocumentEvent e)
    {
        sort();
    }
    public void changedUpdate(DocumentEvent e)
    {
        sort();
    }

    /**
     * 排序单词函数
     */
    private void sort()
    {
        String regex="[\\s\\d\\p{Punct}]+";
        String inputStr=inputArea.getText();
        String[] words=inputStr.split(regex);
        Arrays.sort(words);
        outputArea.setText(null);
        for(String temp:words)
        {
            outputArea.append(temp+",");
        }
    }
}

public class MenuItemListener implements ActionListener {
    private JTextArea inputArea,outputArea;
    public void setInputArea(JTextArea inputArea)
    {
        this.inputArea=inputArea;

    }
    public void setOutputArea(JTextArea outputArea)
    {
        this.outputArea=outputArea;
    }


    public void actionPerformed(ActionEvent e)
    {
        //判断按下的是哪个菜单项,因为3个菜单项共有一个Listener
        String actionCommand=e.getActionCommand();
        if(actionCommand.equals("copy"))
        {
            outputArea.copy();
        }else if(actionCommand.equals("cut"))
        {
            outputArea.cut();
        }else if(actionCommand.equals("paste"))
        {
            inputArea.paste();
        }
    }
}
public class DocumentForm extends JFrame {
    private JTextArea inputText,outputText;
    private JMenuBar menuBar;
    private JMenu menu;
    private JMenuItem copy,cut,paste;
    //监听器
    private EditorListener editorListener;
    private MenuItemListener menuItemListener;

    public DocumentForm()
    {
        //GUI部分
        setLayout(new FlowLayout());
        inputText=new JTextArea(15,20);
        outputText=new JTextArea(15,20);
        outputText.setLineWrap(true);//设置文本区自动换行
        outputText.setWrapStyleWord(true);//设置自动换行,以单词
        menuBar=new JMenuBar();
        menu=new JMenu("编辑");
        copy=new JMenuItem("复制");
        cut=new JMenuItem("剪切");
        paste=new JMenuItem("粘贴");
        copy.setActionCommand("copy");//设置代号-为使MenuItemListener能够判别具体的是哪个菜单项被点击
        cut.setActionCommand("cut");//同上
        paste.setActionCommand("paste");//同上
        //将菜单项加入菜单中
        menu.add(copy);
        menu.add(cut);
        menu.add(paste);
        //菜单加入菜单条
        menuBar.add(menu);
        //界面加入这些组件,以滚动文本域的方式
        add(new JScrollPane(inputText));
        add(new JScrollPane(outputText));
        setJMenuBar(menuBar);
        setVisible(true);
        setBounds(100,100,590,500);
        setTitle("单词排序");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        //设置监听器
        editorListener=new EditorListener();
        menuItemListener=new MenuItemListener();
        editorListener.setInputArea(inputText);
        editorListener.setOutputArea(outputText);
        menuItemListener.setInputArea(inputText);
        menuItemListener.setOutputArea(outputText);
        //添加监听器
        inputText.getDocument().addDocumentListener(editorListener);//DocumentListener
        //菜单项中3个的Listener使用的是相同的
        copy.addActionListener(menuItemListener);
        cut.addActionListener(menuItemListener);
        paste.addActionListener(menuItemListener);

    }
}
public class Main {
    public static void main(String []args)
    {
        DocumentForm form=new DocumentForm();
    }
}

效果如下
在这里插入图片描述

上一篇:Java swing GUI 编程
https://blog.csdn.net/tanyu159/article/details/89047942
下一篇:Java swing开发窗体程序(三)事件(Mouse,Foucs,Key,Window)
https://blog.csdn.net/tanyu159/article/details/89113100

【!!!】欢迎关注我的个人线上课堂https://www.zuikakuedu.cn,内含JavaWeb与Unity游戏开发实战教程,完全免费!,Csdn博客涉及的课程资料也在该网站上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

最咔酷学院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值