• JComboBox实现时间控件


    1.认识JComboBox控件

    最近学习使用了JComboBox组件;

    在学习使用了JList以及Jtree组件之后,对于使用JComboBox还是很轻松的。

    JcomboBox的其实也是由一个Model模型,一个Render渲染器组成,在JComboBox里面,默认的是实现文字或者图片的列表,所以想要实现图片加文字的效果就要自己去重写他的渲染器。

    首先,一个JComboBox的构造方法,可以看一下他的源代码,最近发现看他的源代码比起看API文档是要清楚很多。

      public JComboBox(ComboBoxModel<E> aModel) {
            super();
            setModel(aModel);
            init();
        }
        public JComboBox(E[] items) {
            super();
            setModel(new DefaultComboBoxModel<E>(items));
            init();
        }
        public JComboBox(Vector<E> items) {
            super();
            setModel(new DefaultComboBoxModel<E>(items));
            init();
        }
        public JComboBox() {
            super();
            setModel(new DefaultComboBoxModel<E>());
            init();
        }
    

    所以这里也可以看出我们的JComboBox在构造的时候就必须实例化一个Model,当我们直接给的是一组数据的时候,那么JcomboBox则会根据这组数据去创建一个DefaultComboBoxModel,把它设为JcomboBox的model。而也可以直接传入一个实例化的model。然后看一下DefaultComboBoxModel的构造函数,源码如下:

     /**
         * Constructs a DefaultComboBoxModel object initialized with
         * an array of objects.
         *
         * @param items  an array of Object objects
         */
        public DefaultComboBoxModel(final E items[]) {
            objects = new Vector<E>();
            objects.ensureCapacity( items.length );
    
            int i,c;
            for ( i=0,c=items.length;i<c;i++ )
                objects.addElement(items[i]);
    
            if ( getSize() > 0 ) {
                selectedObject = getElementAt( 0 );
            }
        }
    
        /**
         * Constructs a DefaultComboBoxModel object initialized with
         * a vector.
         *
         * @param v  a Vector object ...
         */
        public DefaultComboBoxModel(Vector<E> v) {
            objects = v;
    
            if ( getSize() > 0 ) {
                selectedObject = getElementAt( 0 );
            }
        }
    

    在DefaultComboBoxModel里面,他只有一下的两个属性:

      Vector<E> objects;
        Object selectedObject;

    一个是Vector对象,一个是一个Object对象,一个是存储当前的JcomboBox里面显示的数据,当传入的是一个数组的时候,也会存放在objects这个对象中,一个是存放选择的数据。在默认情况下,如果自己没有设置的话,刚开始是默认设置选择第一数据。

    对于渲染器,JcomboBox的的渲染器和Jlist的渲染器是一样的,是ListCellRenderer。

    public class UserJComboBoxRenderer extends JLabel implements ListCellRenderer {
    
    	@Override
    	public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
    			boolean cellHasFocus) {
    		
            User user=(User)value; 
    	this.setIcon(null);	
    	if(index!=-1){			
    	ImageIcon img=user.getImg();
    	img.setImage(img.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT));
    	this.setText(user.getID());
    	this.setIcon(img);
    	}else
    	this.setText(user.getID());    
    	return this;
    	}
    }

    这是我为我的QQ聊天登入界面,写的一个用户输入账号写的一个JComboBox组件。

    这里可以注意一点的是, index的值,JComboBox是由可编辑字段与下拉列表组合的组件,也就是一个输入框以及一个下拉列表组合。在JcomboBox中选中的元素由下标-1标识,所以我们可以通过下标来设置达到不一样的效果,这里设置的是当选中了,在输入框中只显示文字。

    在下拉列表中则是显示文字和图片。

    JComboBox加监听:

    JComboBox设置为当他可以编辑的时候,直接给他加上焦点监听,是不起作用的。

    comboBox.addFocusListener(l);//当JComboBox为可以编辑时,是监听不起作用。

    而是需要通过给JcomboBox的编辑的那个面板加上监听,如下:

    comboBox.getEditor().getEditorComponent().addFocusListener(l);

    这样监听才起作用。

    2.自定义年月日控件

    用JComboBox实现选择年月日(出生日期)

    思路是:

    1定义一个CalendarChooser 类继承自JPanel。其中有三个JcomboBox属性,分别表示年,月,日;

    private JComboBox<String> year;
    private JComboBox<String> date;
    private JComboBox<String> month;

    2.在构造方法中实例化上述三个属性,分别给各自的Item赋值;

    3.把他们添加到面板JPanel上(也就是该类本身);同时设置好布局(采用的是BorderLayout布局方式);

    4.加上监听,month的Item的依据是选择的年份,然后date的Item则是同时依据year和month;也就是没有选择年份的时候就不能显示月份,没有年份和月份的时候,date就不能显示数据。

    具体实现:

    重点是设置year,date,month这三个JcomboBox的属性Item:

    1.设置year的属性,

    通过Calendar.getInstance();创建一个Calendar对象。然后根据这个对象获取到当前时间的年份,然后利用一个for循环,把当前年,以及过去的80年添加到里面去。在year这个控件里面Item放入80个年份,提供选择;

    Calendar cal = Calendar.getInstance();
    /**
         * @param year
         *            the year to set
         */
        public void setYearItem(JComboBox<String> year, Calendar cal) {
            int nowyear = cal.getWeekYear();
            for (int i = 0; i < 80; i++) {
                year.addItem(nowyear-- + "年");
            }
        }

    2.设置month的Item属性

    年份是不变的,但是月份是要随着年份的改变而变化,所以我们需要对其进行判断,如果选择的是当前的年份的话,则month里面的Item值只到当前月份。主要考虑的是今年的月份只到当前的月份。

            /**
    	 * @param month
    	 *            the month to set
    	 */
    	public void setMonthItem(JComboBox<String> month, Calendar cal) {
    		month.removeAllItems();
    		int nowmonth;//记录选择的年份的月数
    		if (year.getSelectedItem().equals(cal.getWeekYear() + "年")) {
    			nowmonth = cal.get(Calendar.MONTH) + 1;
    		} else {
    			nowmonth = 12;
    		}
    		for (int i = 1; i <= nowmonth; i++) {
    			month.addItem(i + "月");
    		}
    		month.setSelectedIndex(0);
    	}

    3.设置date的Item属性

    天数根据选择的月份和年份进行添加;

    public void setDateItem(JComboBox<String> date, Calendar cal) {
    	date.removeAllItems();
    	int nowdate = 0;// 当前月的总天数;
    	if (month.getItemCount() != 0) {
            if (year.getSelectedItem().equals(cal.getWeekYear() + "年")&& month.getSelectedIndex() == month.getItemCount() - 1) {
    		nowdate = cal.get(Calendar.DATE);
    	} else {
                   /** 把字符串进行拆分,去掉年和月 */
    		String s = (String) year.getSelectedItem();
    		String year = s.substring(0, s.length() - 1);
    		s = (String) month.getSelectedItem();
    		String month = s.substring(0, s.length() - 1);
    		nowdate = getDaysByYearMonth(cal, Integer.parseInt(year), Integer.parseInt(month));
    			}
            	for (int i = 1; i <= nowdate; i++) {
    			date.addItem(i + "日");
    			}
    		}
    	}

    其中根据年月获取天数的方法:

    	public int getDaysByYearMonth(Calendar cal, int year, int month) {
    		/*
    		 * cal.set(Calendar.YEAR,year); 
    		 * cal.set(Calendar.MONTH, month - 1);
    		 * cal.set(Calendar.DATE, 1); 
    		 * 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值。
    		 */
    		cal.set(year, month - 1, 1);
                    // 向指定日历字段添加指定(有符号的)时间量,不更改更大的字段。负的时间量意味着向下滚动。
    		cal.roll(Calendar.DATE, -1);
    		int maxDate = cal.get(Calendar.DATE);
    		return maxDate;
    	}

    然后在给他们加上监听:

    只需要个年份和月份加上监听就可以了。年份的改变会影响月和日,月的改变会影响日的改变。

    public void addListener() {
    		CalendarListener l = new CalendarListener(this);
    		year.addItemListener(l);
    		month.addItemListener(l);
    	}

    然后具体的监听事件:

    public class CalendarListener implements ItemListener {
    	CalendarChooser ca;
    	public CalendarListener(CalendarChooser ca) {
    		this.ca = ca;
    	}
    	@SuppressWarnings("unchecked")
    	@Override
    	public void itemStateChanged(ItemEvent e) {
    	JComboBox<String> jcombox = (JComboBox<String>) e.getSource();
    	if (jcombox.getName().equals("年")) {
                  //年份改变然后月份进行改变;
    	    ca.setMonthItem(ca.getMonth(),Calendar.getInstance());
                     //年份改变,天数进行改变;
               // ca.setDateItem(ca.getDate(),Calendar.getInstance());          
    		} else if (jcombox.getName().equals("月")) {
    		    ca.setDateItem(ca.getDate(),Calendar.getInstance());
    		}
    
    	}
    }

    注意的是,itemStateChanged监听方法会随着item的值的改变而改变,即使我们不去选择。只要item的值发生了变化,该方法就会被调用。

     ca.setMonthItem(ca.getMonth(),Calendar.getInstance());

    所以我们在执行上面这行代码的时候,下面也会被执行:

    else if (jcombox.getName().equals("月")) {
    		    ca.setDateItem(ca.getDate(),Calendar.getInstance());
    		}

    以上就是全部核心代码了。

    效果图:

    另外图中的性别是:JRadioButton,同时用ButtonGroup进行包装(ButtonGroup用于为一组按钮创建一个多斥作用域。 使用相同的 ButtonGroup对象创建一组按钮意味着“开启”其中一个按钮时,将关闭组中的其他所有按钮)。

  • 相关阅读:
    python3 -- 堆(heapq)
    二叉堆的实现(最大堆)
    解决layui layer.load() Ajax提交时,只在结束闪一下
    两个for循环嵌套,写成一个列表生成式
    time模块,计算当前时间和时间差
    私有化&property
    面向对象魔术方法之__str__()方法
    面向对象魔术方法-__del__()方法
    面向对象之魔术方法__init__()和__new__()
    Django的自定义标签
  • 原文地址:https://www.cnblogs.com/hesi/p/6279741.html
Copyright © 2020-2023  润新知