版权声明:本文为博主原创文章,未经博主允许不得转载。

 

目录(?)[+]

 

参考资料:

http://263229365.iteye.com/blog/1040329

https://www.java.net/node/650758

https://community.oracle.com/thread/2332288?start=0&tstart=0

问题的产生:

在看JComboBox组件的监听事件时,运行讲解到的实例(增加了几个输出语句来跟踪它的反应)碰到下面的问题:

1, JComboBox组件在添加了ActionListener和ItemListener监听器时, 两个监听器都对JComboBox值的改变做出了相应的操作。

2, 尤其是ActionListener的事件处理,不管怎么样都始终执行了两次。。。。

(1)运行下面的程序代码:

  1. package org.forfan06.jcomboboxdemo;
  2. import java.awt.Container;
  3. import java.awt.Font;
  4. import java.awt.GridLayout;
  5. import java.awt.event.WindowAdapter;
  6. import java.awt.event.WindowEvent;
  7. import java.awt.event.ItemListener;
  8. import java.awt.event.ItemEvent;
  9. import java.awt.event.ActionEvent;
  10. import java.awt.event.ActionListener;
  11. import javax.swing.BorderFactory;
  12. import javax.swing.JComboBox;
  13. import javax.swing.JFrame;
  14. import javax.swing.JLabel;
  15. class MyComboBox implements ActionListener, ItemListener{
  16. private JFrame jframe = new JFrame("Welcome to my blog");
  17. private Container container = jframe.getContentPane();
  18. private JComboBox jcb1 = null;
  19. private JLabel label = new JLabel("www.csnd.net");
  20. private String fontSize[] = {"10", "12", "14", "16", "18", "20", "22", "24", "26", "48", "72"};
  21. public MyComboBox(){
  22. this.jframe.setLayout(new GridLayout(2, 1));
  23. this.jcb1 = new JComboBox(this.fontSize);
  24. jcb1.setBorder(BorderFactory.createTitledBorder("请选择显示文字大小"));
  25. jcb1.addItemListener(this);
  26. jcb1.addActionListener(this);
  27. jcb1.setMaximumRowCount(3);;
  28. jcb1.setEditable(true);
  29. jcb1.configureEditor(jcb1.getEditor(), "12");
  30. this.changeFontSize(12);
  31. container.add(this.jcb1);
  32. container.add(label);
  33. this.jframe.setSize(300, 150);
  34. this.jframe.setVisible(true);
  35. this.jframe.addWindowListener(new WindowAdapter(){
  36. public void windowClosing(WindowEvent e){
  37. System.exit(1);
  38. }
  39. });
  40. }
  41. public void itemStateChanged(ItemEvent e){
  42. if(e.getStateChange() == ItemEvent.SELECTED){
  43. String itemSize = (String) e.getItem();
  44. try{
  45. System.out.println("---ItemEvent performed:" + e.paramString() + "---");
  46. this.changeFontSize(Integer.parseInt(itemSize));  //改变字体
  47. }catch(Exception ex){
  48. }
  49. }
  50. }
  51. public void actionPerformed(ActionEvent e){
  52. String itemSize = (String) this.jcb1.getSelectedItem();
  53. int size = 12;
  54. try{
  55. size = Integer.parseInt(itemSize);
  56. }catch(Exception ex){
  57. this.jcb1.getEditor().setItem("输入的不是数字。");
  58. }
  59. System.out.println("---action performed " +e.getActionCommand() + "---");
  60. this.changeFontSize(size);
  61. if(!this.isExists(itemSize)){
  62. this.jcb1.addItem(jcb1.getSelectedItem());
  63. }
  64. }
  65. public boolean isExists(String item){
  66. boolean flag = false;
  67. for(int i = 0; i < this.jcb1.getItemCount(); i++){
  68. if(item.equals(this.jcb1.getItemAt(i))){
  69. flag = true;
  70. }
  71. }
  72. return flag;
  73. }
  74. public void changeFontSize(int size){
  75. Font fnt = new Font("Serief", Font.BOLD, size);
  76. this.label.setFont(fnt);
  77. }
  78. }
  79. public class JComboBoxDemo03 {
  80. public static void main(String args[]){
  81. MyComboBox myComboBox = new MyComboBox();
  82. }
  83. }

(2)查看运行结果:

Option 1: 从下拉列表里面选择一个值

  1. ---ItemEvent performed: ITEM_STATE_CHANGED, item=48, stateChange=SELECTED---
  2. ---action performed comboBoxChanged---

Option 2: 直接键盘输入一个值

  1. ---ItemEvent performed: ITEM_STATE_CHANGED, item=25, stateChange=SELECTED---
  2. ---action performed comboBoxChanged---
  3. ---action performed comboBoxEdited---

可以发现,如果此时在JComboBox同时加入ItemListener和 ActionListener的话,两个监听器都会做出相应的动作(并且ActionEvent做出了两次反应 twice)!!!

分析:

1, 如果在覆些ItemListener的itemStateChanged方法中的判断去掉的话,ItemListener同样也会做出两次动作!!第一次是前一个值的DESELECTED触发;第二次是后一个值的SELECTED触发。 这里通过判断触发源的StateChange来进行过滤,只对后一次值的SELECTED做出动作!!!!!

  • ItemListener接口中定义的itemStateChanged(ItemEvent e)将执行需要在已选定(或已取消选定)项时发生的操作;
  • 上次被选中的项的State由SELECTED变为DESELECTED,即取消选择;
  • 本次选中的项的State由DESELECTED变为SELECTED,即新选中;
  • itemStateChanged()事件与itemState有关!!!itemState在这里有两个状态,Selected和Ddselected

所以itemStateChanged事件中的代码要被执行两次!!!!!!

2, https://www.java.net/node/650758

查看JComboBox的源代码例子,对于JComboBox有个actionCommand的String存在!!!其可能的两个值“comboBoxChanged”和“comboBoxEdited”被hardcoded到源码里面了。同样也造成了有两个ActionPerformed产生了。

对于有两个actionPerformed产生,有以下解决方案:

Step1, 保存上次选定项的值

Step2, 仅对选项值是新(新选项并且该选项的值不等于上次选定项的值)的事件进行捕获

3,针对ActionListener,因为与两次的输出是当actionCommand的值分别是comboBoxChanged和comboBoxEdited做出reaction。

由于actionCommand的值是String类型,所以只需要do a simple equals test 就可以了。。修改actionPerformed(ActionEvent e)方法如下就可以过滤掉comboBoxEdited的触发事件了

  1. public void actionPerformed(ActionEvent e){
  2. if(e.getActionCommand().equals("comboBoxChanged")){
  3. String itemSize = (String) this.jcb1.getSelectedItem();
  4. int size = 12;
  5. try{
  6. size = Integer.parseInt(itemSize);
  7. }catch(Exception ex){
  8. this.jcb1.getEditor().setItem("输入的不是数字。");
  9. }
  10. System.out.println("---action performed " +e.getActionCommand() + "---");
  11. this.changeFontSize(size);
  12. if(!this.isExists(itemSize)){
  13. this.jcb1.addItem(jcb1.getSelectedItem());
  14. }
  15. }
  16. }

还有另外一种解决方案来自 https://community.oracle.com/thread/2332288?start=0&tstart=0  同学

  1. //The Listener has to be attached to the editor in stead of the comboBox itself
  2. comboBox.getEditor().addActionListener(new ActionListener()){
  3. ...
  4. }

但是好像,上面的这个editor监听器的方案不好处理啊。还是我没有找到正确的处理方法~~~它失去了监听JComboBox组件 这一最初始的目的啊~~~~~~~~~

4,JComboBox is a little bit different than other components, because there are two actions, you shouldn't set the command, instead you should check them, as follows.

if ("comboBoxEdited".equals(evt.getActionCommand()))
else if ("comboBoxChanged".equals(evt.getActionCommand()))

总结

1,ActionListener是所有监听器的父类,其他监听器可以监听的事件都可以被它捕获

2, ItemListener用于捕获带Item的组件产生的事件,抽象方法itemStateChanged(ItemEvent e)执行需要在已选定(或已取消选定)项时发生的操作

3, (仔细查看event事件)ActionListener报告的2个不同的事件: 一个是编辑文本框 comboBoxEdited,另外一个是选定值  comboBoxChanged。

问题的解决:

1, 网上有人说针对JComboBox一般添加ItemListener监听器即可 (ActionListener是所有监听器的父类,其他监听器可以监听的事件都可以被ActionListener捕获)

2, 通过对ActionEvent的actionCommand值的判断,来过滤掉不需要的监听事件。 例如,我们只需要捕获值的改变(actionCommand = comboBoxChanged)。

3, 增加一点ItemListener监听器的事件的过滤,是通过事件的 getStateChanged()的值(它只有两个值: ItemEvent.SELECTED  和  ItemEvent.DESELECTED)来判断的。

JAVA JComboBox的监听事件(ActionListener、ItemListener)的更多相关文章

  1. [置顶] java Gui 键盘监听事件

    简单写一个java Gui键盘监听事件,实现的效果就是按下键盘控制台输出你按下的键.比如:按下A控制台就输出A 效果如图: 以下把实现的效果分为几个步骤: 1.新建一个窗体类继承窗体: 2.给这个窗体 ...

  2. java中的监听事件

    java监听器实现的类 1.ServletContextListener:对servlet上下文的创建和销毁监听 2.ServletContextAttributeListener:监听servlet ...

  3. Second Day: 关于Button监听事件的三种方法(匿名类、外部类、继承接口)

    第一种:通过匿名类实现对Button事件的监听 首先在XML文件中拖入一个Button按钮,并设好ID,其次在主文件.java中进行控件初始化(Private声明),随后通过SetOnClickLis ...

  4. 一步一步学android之事件篇——单选按钮监听事件

    在平常使用软件的时候,我们经常会碰见一些选择题,例如选择性别的时候,在男和女之间选,前面说过这个情况要用RadioGroup组件,那么点击了之后我们该怎么获取到选择的那个值呢,这就是今天要说的OnCh ...

  5. 横向滑动的listview和其中用到的触摸监听事件详解

    一.首先把横向的listview的代码放上来 HorizontalListView: package com.common.cklibrary.utils.myview; import java.ut ...

  6. springboot13 发布和监听事件

    spring中的事件驱动模型Event(也叫发布订阅模式),是观察者模式的一个典型的应用 好处:业务解耦,在不影响原来业务逻辑的情况下,加入其它业务 场景: app上线后已实现用户注册功能,现需要在用 ...

  7. Android开发 ---基本UI组件8:九宫格布局、setOnItemClickListener()项被选中监听事件

    效果图: 1.activity_main.xml 描述: 定义了一个按钮 <?xml version="1.0" encoding="utf-8"?> ...

  8. Android——监听事件总结

    各种监听事件 1.按钮 Button(1)点击监听 btn_1.setOnClickListener(new View.OnClickListener() { (2)长按监听 btn_1.setOnL ...

  9. spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

随机推荐

  1. mysql为用户开启Trigger的权限

    mysql中trigger的使用也需要权限,如果在使用中出现类似: TRIGGER command denied to user ‘username’@’192.168.0.112′ for tabl ...

  2. 【angular5项目积累总结】文件上传

    <div class="form-group row"> <label class="col-sm-2 col-form-label"> ...

  3. 访问 .obj文件,由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射

    一.错误描述 HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. 最可能的原因: 可 ...

  4. Java中类的线程安全问题

    java中各种集合(字符串类)的线程安全性!!! 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读 ...

  5. Android - 系统开机你知道多少?

    https://github.com/zhantong/interview/blob/master/Android/Android.md#38-android%E7%B3%BB%E7%BB%9F%E5 ...

  6. php实现同一时间内一个账户只允许在一个终端登陆

    在账户表的基础上,我新建了一个账户account_session表,用来记录登录账户的account_id和最新一次登录成功用户的session_id,然后首先要修改登录方法:每次登录成功后,要将登录 ...

  7. git 本地安装

    一.基本安装 1.下载Git   官方地址为:https://git-scm.com/download/win 2.下载完之后,双击安装,全部选择默认. 3.选择安装目录 4.选择组件 5.开始菜单目 ...

  8. 自定义jquery公用方法切换当前tab栏

    经常在项目中需要写到切换当前栏目的展示效果,定义公共方法 //切换当前选中 /** * 全局切换或滑动标签的函数.一般使用active作为当前激活标签的类名,如果已使用其它类名,请将类名作为二参传入 ...

  9. css语法和基本知识

    1.CSS全称为“层叠样式表”,它主要是用于定义HTML内容在浏览器内的显示样式,如文字大小.颜色.字体加粗等. 注:使用CSS样式的一个好处是通过定义某个样式,可以让不同网页位置的文字有着统一的字体 ...

  10. git 报错:error: failed to push some refs to 'https://github.com/Anderson-An/******.git'(已解决)

    提交push 报错: $ git push origin masterTo https://github.com/Anderson-An/******.git ! [rejected] master ...