JAVA SWING 日期选择控件(目前支持JLable和JTextField)

package com.monitor.date;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
 
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
 
/** 
 * 日期选择器,可以指定日期的显示格式 
 */
public class DateChooser extends JPanel {
 
	private static final long serialVersionUID = 4529266044762990227L;
 
	private Date initDate;
	private Calendar now = Calendar.getInstance();
	private Calendar select;
	private JPanel monthPanel;//月历  
	private JP1 jp1;//四块面板,组成  
	private JP2 jp2;
	private JP3 jp3;
	private JP4 jp4;
	private Font font = new Font("宋体", Font.PLAIN, 12);
	private final LabelManager lm = new LabelManager();
	private SimpleDateFormat sdf;
	private boolean isShow = false;
	private Popup pop;
 
	private JComponent showDate;
 
	public static DateChooser getInstance() {
		return new DateChooser();
	}
 
	public static DateChooser getInstance(Date date) {
		return new DateChooser(date);
	}
 
	public static DateChooser getInstance(String format) {
		return new DateChooser(format);
	}
 
	public static DateChooser getInstance(Date date, String format) {
		return new DateChooser(date, format);
	}
 
	/** 
	 * Creates a new instance of DateChooser 
	 */
	private DateChooser() {
		this(new Date());
	}
 
	private DateChooser(Date date) {
		this(date, "yyyy年MM月dd日");
	}
 
	private DateChooser(String format) {
		this(new Date(), format);
	}
 
	private DateChooser(Date date, String format) {
		initDate = date;
		sdf = new SimpleDateFormat(format);
		select = Calendar.getInstance();
		select.setTime(initDate);
		initPanel();
	}
 
	/** 
	 * 是否允许用户选择 
	 */
	public void setEnabled(boolean b) {
		super.setEnabled(b);
		showDate.setEnabled(b);
	}
 
	/** 
	 *得到当前选择框的日期 
	 */
	public Date getDate() {
		return select.getTime();
	}
 
	public String getStrDate() {
		return sdf.format(select.getTime());
	}
 
	public String getStrDate(String format) {
		sdf = new SimpleDateFormat(format);
		return sdf.format(select.getTime());
	}
 
	//根据初始化的日期,初始化面板  
	private void initPanel() {
		monthPanel = new JPanel(new BorderLayout());
		monthPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
		JPanel up = new JPanel(new BorderLayout());
		up.add(jp1 = new JP1(), BorderLayout.NORTH);
		up.add(jp2 = new JP2(), BorderLayout.CENTER);
		monthPanel.add(jp3 = new JP3(), BorderLayout.CENTER);
		monthPanel.add(up, BorderLayout.NORTH);
		monthPanel.add(jp4 = new JP4(), BorderLayout.SOUTH);
		this.addAncestorListener(new AncestorListener() {
			public void ancestorAdded(AncestorEvent event) {
 
			}
 
			public void ancestorRemoved(AncestorEvent event) {
 
			}
 
			//只要祖先组件一移动,马上就让popup消失  
			public void ancestorMoved(AncestorEvent event) {
				hidePanel();
			}
		});
	}
 
	public void register(final JComponent showDate) {
		this.showDate = showDate;
 
		showDate.setRequestFocusEnabled(true);
		showDate.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent me) {
				showDate.requestFocusInWindow();
			}
		});
		this.setBackground(Color.WHITE);
		this.add(showDate, BorderLayout.CENTER);
		this.setPreferredSize(new Dimension(90, 25));
		this.setBorder(BorderFactory.createLineBorder(Color.GRAY));
		showDate.addMouseListener(new MouseAdapter() {
			public void mouseEntered(MouseEvent me) {
				if (showDate.isEnabled()) {
					showDate.setCursor(new Cursor(Cursor.HAND_CURSOR));
					showDate.setForeground(Color.RED);
				}
			}
 
			public void mouseExited(MouseEvent me) {
				if (showDate.isEnabled()) {
					showDate.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					showDate.setForeground(Color.BLACK);
				}
			}
 
			public void mousePressed(MouseEvent me) {
				if (showDate.isEnabled()) {
					showDate.setForeground(Color.CYAN);
					if (isShow) {
						hidePanel();
					} else {
						showPanel(showDate);
					}
				}
			}
 
			public void mouseReleased(MouseEvent me) {
				if (showDate.isEnabled()) {
					showDate.setForeground(Color.BLACK);
				}
			}
		});
		showDate.addFocusListener(new FocusListener() {
			public void focusLost(FocusEvent e) {
				hidePanel();
			}
 
			public void focusGained(FocusEvent e) {
 
			}
		});
	}
 
	//根据新的日期刷新  
	private void refresh() {
		jp1.updateDate();
		jp2.updateDate();
		jp3.updateDate();
		jp4.updateDate();
		SwingUtilities.updateComponentTreeUI(this);
	}
 
	//提交日期  
	private void commit() {
		//TODO add other components here
		if (showDate instanceof JTextField) {
			((JTextField) showDate).setText(sdf.format(select.getTime()));
		}else if (showDate instanceof JLabel) {
			((JLabel) showDate).setText(sdf.format(select.getTime()));
		}
 
		hidePanel();
	}
 
	//隐藏日期选择面板  
	private void hidePanel() {
		if (pop != null) {
			isShow = false;
			pop.hide();
			pop = null;
		}
	}
 
	//显示日期选择面板  
	private void showPanel(Component owner) {
		if (pop != null) {
			pop.hide();
		}
		Point show = new Point(0, showDate.getHeight());
		SwingUtilities.convertPointToScreen(show, showDate);
		Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
		int x = show.x;
		int y = show.y;
		if (x < 0) {
			x = 0;
		}
		if (x > size.width - 295) {
			x = size.width - 295;
		}
		if (y < size.height - 170) {
		} else {
			y -= 188;
		}
		pop = PopupFactory.getSharedInstance().getPopup(owner, monthPanel, x, y);
		pop.show();
		isShow = true;
	}
 
	/** 
	 * 最上面的面板用来显示月份的增减 
	 */
	private class JP1 extends JPanel {
		private static final long serialVersionUID = -5638853772805561174L;
		JLabel yearleft, yearright, monthleft, monthright, center, centercontainer;
 
		public JP1() {
			super(new BorderLayout());
			this.setBackground(new Color(160, 185, 215));
			initJP1();
		}
 
		private void initJP1() {
			yearleft = new JLabel("  <<", JLabel.CENTER);
			yearleft.setToolTipText("上一年");
			yearright = new JLabel(">>  ", JLabel.CENTER);
			yearright.setToolTipText("下一年");
			yearleft.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
			yearright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
 
			monthleft = new JLabel("  <", JLabel.RIGHT);
			monthleft.setToolTipText("上一月");
			monthright = new JLabel(">  ", JLabel.LEFT);
			monthright.setToolTipText("下一月");
			monthleft.setBorder(BorderFactory.createEmptyBorder(2, 30, 0, 0));
			monthright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 30));
 
			centercontainer = new JLabel("", JLabel.CENTER);
			centercontainer.setLayout(new BorderLayout());
			center = new JLabel("", JLabel.CENTER);
 
			centercontainer.add(monthleft, BorderLayout.WEST);
			centercontainer.add(center, BorderLayout.CENTER);
			centercontainer.add(monthright, BorderLayout.EAST);
 
			this.add(yearleft, BorderLayout.WEST);
			this.add(centercontainer, BorderLayout.CENTER);
			this.add(yearright, BorderLayout.EAST);
			this.setPreferredSize(new Dimension(295, 25));
 
			updateDate();
 
			yearleft.addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent me) {
					yearleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
					yearleft.setForeground(Color.RED);
				}
 
				public void mouseExited(MouseEvent me) {
					yearleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					yearleft.setForeground(Color.BLACK);
				}
 
				public void mousePressed(MouseEvent me) {
					select.add(Calendar.YEAR, -1);
					yearleft.setForeground(Color.WHITE);
					refresh();
				}
 
				public void mouseReleased(MouseEvent me) {
					yearleft.setForeground(Color.BLACK);
				}
			});
			yearright.addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent me) {
					yearright.setCursor(new Cursor(Cursor.HAND_CURSOR));
					yearright.setForeground(Color.RED);
				}
 
				public void mouseExited(MouseEvent me) {
					yearright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					yearright.setForeground(Color.BLACK);
				}
 
				public void mousePressed(MouseEvent me) {
					select.add(Calendar.YEAR, 1);
					yearright.setForeground(Color.WHITE);
					refresh();
				}
 
				public void mouseReleased(MouseEvent me) {
					yearright.setForeground(Color.BLACK);
				}
			});
			monthleft.addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent me) {
					monthleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
					monthleft.setForeground(Color.RED);
				}
 
				public void mouseExited(MouseEvent me) {
					monthleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					monthleft.setForeground(Color.BLACK);
				}
 
				public void mousePressed(MouseEvent me) {
					select.add(Calendar.MONTH, -1);
					monthleft.setForeground(Color.WHITE);
					refresh();
				}
 
				public void mouseReleased(MouseEvent me) {
					monthleft.setForeground(Color.BLACK);
				}
			});
			monthright.addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent me) {
					monthright.setCursor(new Cursor(Cursor.HAND_CURSOR));
					monthright.setForeground(Color.RED);
				}
 
				public void mouseExited(MouseEvent me) {
					monthright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					monthright.setForeground(Color.BLACK);
				}
 
				public void mousePressed(MouseEvent me) {
					select.add(Calendar.MONTH, 1);
					monthright.setForeground(Color.WHITE);
					refresh();
				}
 
				public void mouseReleased(MouseEvent me) {
					monthright.setForeground(Color.BLACK);
				}
			});
		}
 
		private void updateDate() {
			center.setText(select.get(Calendar.YEAR) + "年" + (select.get(Calendar.MONTH) + 1) + "月");
		}
	}
 
	private class JP2 extends JPanel {
		private static final long serialVersionUID = -8176264838786175724L;
 
		public JP2() {
			this.setPreferredSize(new Dimension(295, 20));
		}
 
		protected void paintComponent(Graphics g) {
			g.setFont(font);
			g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10);
			g.drawLine(0, 15, getWidth(), 15);
		}
 
		private void updateDate() {
 
		}
	}
 
	private class JP3 extends JPanel {
		private static final long serialVersionUID = 43157272447522985L;
 
		public JP3() {
			super(new GridLayout(6, 7));
			this.setPreferredSize(new Dimension(295, 100));
			initJP3();
		}
 
		private void initJP3() {
			updateDate();
		}
 
		public void updateDate() {
			this.removeAll();
			lm.clear();
			Date temp = select.getTime();
			Calendar select = Calendar.getInstance();
			select.setTime(temp);
			select.set(Calendar.DAY_OF_MONTH, 1);
			int index = select.get(Calendar.DAY_OF_WEEK);
			int sum = (index == 1 ? 8 : index);
			select.add(Calendar.DAY_OF_MONTH, 0 - sum);
			for (int i = 0; i < 42; i++) {
				select.add(Calendar.DAY_OF_MONTH, 1);
				lm.addLabel(new MyLabel(select.get(Calendar.YEAR), select.get(Calendar.MONTH), select.get(Calendar.DAY_OF_MONTH)));
			}
			for (MyLabel my : lm.getLabels()) {
				this.add(my);
			}
			select.setTime(temp);
		}
	}
 
	private class MyLabel extends JLabel implements Comparator<MyLabel>, MouseListener, MouseMotionListener {
		private static final long serialVersionUID = 3668734399227577214L;
		private int year, month, day;
		private boolean isSelected;
 
		public MyLabel(int year, int month, int day) {
			super("" + day, JLabel.CENTER);
			this.year = year;
			this.day = day;
			this.month = month;
			this.addMouseListener(this);
			this.addMouseMotionListener(this);
			this.setFont(font);
			if (month == select.get(Calendar.MONTH)) {
				this.setForeground(Color.BLACK);
			} else {
				this.setForeground(Color.LIGHT_GRAY);
			}
			if (day == select.get(Calendar.DAY_OF_MONTH)) {
				this.setBackground(new Color(160, 185, 215));
			} else {
				this.setBackground(Color.WHITE);
			}
		}
 
		public boolean getIsSelected() {
			return isSelected;
		}
 
		public void setSelected(boolean b, boolean isDrag) {
			isSelected = b;
			if (b && !isDrag) {
				int temp = select.get(Calendar.MONTH);
				select.set(year, month, day);
				if (temp == month) {
					SwingUtilities.updateComponentTreeUI(jp3);
				} else {
					refresh();
				}
			}
			this.repaint();
		}
 
		protected void paintComponent(Graphics g) {
			if (day == select.get(Calendar.DAY_OF_MONTH) && month == select.get(Calendar.MONTH)) {
				//如果当前日期是选择日期,则高亮显示  
				g.setColor(new Color(160, 185, 215));
				g.fillRect(0, 0, getWidth(), getHeight());
			}
			if (year == now.get(Calendar.YEAR) && month == now.get(Calendar.MONTH) && day == now.get(Calendar.DAY_OF_MONTH)) {
				//如果日期和当前日期一样,则用红框  
				Graphics2D gd = (Graphics2D) g;
				gd.setColor(Color.RED);
				Polygon p = new Polygon();
				p.addPoint(0, 0);
				p.addPoint(getWidth() - 1, 0);
				p.addPoint(getWidth() - 1, getHeight() - 1);
				p.addPoint(0, getHeight() - 1);
				gd.drawPolygon(p);
			}
			if (isSelected) {//如果被选中了就画出一个虚线框出来  
				Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, new float[] { 2.0f, 2.0f }, 1.0f);
				Graphics2D gd = (Graphics2D) g;
				gd.setStroke(s);
				gd.setColor(Color.BLACK);
				Polygon p = new Polygon();
				p.addPoint(0, 0);
				p.addPoint(getWidth() - 1, 0);
				p.addPoint(getWidth() - 1, getHeight() - 1);
				p.addPoint(0, getHeight() - 1);
				gd.drawPolygon(p);
			}
			super.paintComponent(g);
		}
 
		public boolean contains(Point p) {
			return this.getBounds().contains(p);
		}
 
		private void update() {
			repaint();
		}
 
		public void mouseClicked(MouseEvent e) {
		}
 
		public void mousePressed(MouseEvent e) {
			isSelected = true;
			update();
		}
 
		public void mouseReleased(MouseEvent e) {
			Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
			lm.setSelect(p, false);
			commit();
		}
 
		public void mouseEntered(MouseEvent e) {
		}
 
		public void mouseExited(MouseEvent e) {
		}
 
		public void mouseDragged(MouseEvent e) {
			Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
			lm.setSelect(p, true);
		}
 
		public void mouseMoved(MouseEvent e) {
		}
 
		public int compare(MyLabel o1, MyLabel o2) {
			Calendar c1 = Calendar.getInstance();
			c1.set(o1.year, o2.month, o1.day);
			Calendar c2 = Calendar.getInstance();
			c2.set(o2.year, o2.month, o2.day);
			return c1.compareTo(c2);
		}
	}
 
	private class LabelManager {
		private List<MyLabel> list;
 
		public LabelManager() {
			list = new ArrayList<MyLabel>();
		}
 
		public List<MyLabel> getLabels() {
			return list;
		}
 
		public void addLabel(MyLabel my) {
			list.add(my);
		}
 
		public void clear() {
			list.clear();
		}
 
		@SuppressWarnings("unused")
		public void setSelect(MyLabel my, boolean b) {
			for (MyLabel m : list) {
				if (m.equals(my)) {
					m.setSelected(true, b);
				} else {
					m.setSelected(false, b);
				}
			}
		}
 
		public void setSelect(Point p, boolean b) {
			//如果是拖动,则要优化一下,以提高效率  
			if (b) {
				//表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和  
				//将要显示的标签找到了就可以了  
				boolean findPrevious = false, findNext = false;
				for (MyLabel m : list) {
					if (m.contains(p)) {
						findNext = true;
						if (m.getIsSelected()) {
							findPrevious = true;
						} else {
							m.setSelected(true, b);
						}
					} else if (m.getIsSelected()) {
						findPrevious = true;
						m.setSelected(false, b);
					}
					if (findPrevious && findNext) {
						return;
					}
				}
			} else {
				MyLabel temp = null;
				for (MyLabel m : list) {
					if (m.contains(p)) {
						temp = m;
					} else if (m.getIsSelected()) {
						m.setSelected(false, b);
					}
				}
				if (temp != null) {
					temp.setSelected(true, b);
				}
			}
		}
 
	}
 
	private class JP4 extends JPanel {
		private static final long serialVersionUID = -6391305687575714469L;
 
		public JP4() {
			super(new BorderLayout());
			this.setPreferredSize(new Dimension(295, 20));
			this.setBackground(new Color(160, 185, 215));
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
			final JLabel jl = new JLabel("今天: " + sdf.format(new Date()));
			jl.setToolTipText("点击选择今天日期");
			this.add(jl, BorderLayout.CENTER);
			jl.addMouseListener(new MouseAdapter() {
				public void mouseEntered(MouseEvent me) {
					jl.setCursor(new Cursor(Cursor.HAND_CURSOR));
					jl.setForeground(Color.RED);
				}
 
				public void mouseExited(MouseEvent me) {
					jl.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
					jl.setForeground(Color.BLACK);
				}
 
				public void mousePressed(MouseEvent me) {
					jl.setForeground(Color.WHITE);
					select.setTime(new Date());
					refresh();
					commit();
				}
 
				public void mouseReleased(MouseEvent me) {
					jl.setForeground(Color.BLACK);
				}
			});
		}
 
		private void updateDate() {
 
		}
	}
 
	public static void main(String[] args) {
		DateChooser dateChooser1 = DateChooser.getInstance("yyyy-MM-dd");
		DateChooser dateChooser2 = DateChooser.getInstance("yyyy-MM-dd");
		JTextField showDate1 = new JTextField("单击选择日期");
		JLabel showDate2 = new JLabel("单击选择日期");
 
		dateChooser1.register(showDate1);
		dateChooser2.register(showDate2);
 
		JFrame jf = new JFrame("测试日期选择器");
		jf.add(showDate1, BorderLayout.NORTH);
		jf.add(showDate2, BorderLayout.SOUTH);
		jf.pack();
		jf.setLocationRelativeTo(null);
		jf.setVisible(true);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
可以使用网格布局的 `GridBagConstraints` 类,设置 `gridx` 和 `gridy` 属性来控制组件的位置,设置 `gridwidth` 属性来跨越多个网格。可以使用 `anchor` 属性让组件在网格中居中。具体步骤如下: 1. 创建一个JPanel面板,使用网格布局管理器。 ``` JPanel panel = new JPanel(new GridBagLayout()); ``` 2. 创建JLabel和JTextField组件。 ``` JLabel label = new JLabel("Label:"); JTextField textField = new JTextField(20); ``` 3. 创建一个 `GridBagConstraints` 对象,设置组件在网格中的位置和跨越的网格数,以及组件在网格中的对齐方式。 ``` GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; // 在第0列 c.gridy = 0; // 在第0行 c.gridwidth = 2; // 跨越两个网格 c.anchor = GridBagConstraints.CENTER; // 居中对齐 ``` 4. 将JLabel和JTextField组件添加到面板中。 ``` panel.add(label, c); // 添加JLabel c.gridx = 2; // 在第2列 c.gridwidth = 3; // 跨越三个网格 panel.add(textField, c); // 添加JTextField ``` 5. 将面板添加到JFrame窗口中。 ``` frame.add(panel); ``` 完整代码示例: ``` import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class GridBagLayoutExample { public static void main(String[] args) { JFrame frame = new JFrame("GridBagLayout Example"); JPanel panel = new JPanel(new GridBagLayout()); JLabel label = new JLabel("Label:"); JTextField textField = new JTextField(20); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; panel.add(label, c); c.gridx = 2; c.gridwidth = 3; panel.add(textField, c); frame.add(panel); frame.pack(); frame.setVisible(true); } } ``` 以上代码会在第0行中,居中放置一个JLabel和JTextField组件。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值