Swing之日期选择器

直接上代码,非常完整的代码,copy可以直接运行:

package component;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;

import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * 时间选择器
 * 
 * @author tang
 * @since 2014/7/18
 * 
 */
@SuppressWarnings("serial")
public class DateChooser extends JPanel {

	public static void main(String[] args) {
		final JFrame frame = new JFrame("时间选择器");
		frame.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 20));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(500, 500);
		frame.setLocationRelativeTo(null);

		final JTextField textField = new JTextField(10);
		frame.add(textField);

		final JButton buttonLeft = new JButton("选择日期(弹出的对话框以此按钮左对齐)");
		buttonLeft.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				Dimension dialogSize = new Dimension(400, 250);
				Point screen = buttonLeft.getLocationOnScreen();
				Point point = new Point(screen.x, screen.y + buttonLeft.getPreferredSize().height + 5);

				DateChooser dateChooser = new DateChooser();
				String selectedDate = dateChooser.showDateDialog(frame, point, dialogSize);
				if (dateChooser.isConfirm()) {
					textField.setText(selectedDate);
				}
			}
		});
		frame.add(buttonLeft);

		final JButton buttonRight = new JButton("选择日期(弹出的对话框以此按钮右对齐)");
		buttonRight.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {

				Dimension dialogSize = new Dimension(400, 250);
				int x = dialogSize.width - buttonRight.getPreferredSize().width;
				Point screen = buttonRight.getLocationOnScreen();
				Point point = new Point(screen.x - x, screen.y + buttonRight.getPreferredSize().height + 5);

				DateChooser dateChooser = new DateChooser();
				String selectedDate = dateChooser.showDateDialog(frame, point, dialogSize);
				if (dateChooser.isConfirm()) {
					textField.setText(selectedDate);
				}
			}
		});
		frame.add(buttonRight);

		frame.setVisible(true);
	}

	protected final int startYear;
	protected final int lastYear;

	protected final String[] weekStrings = { "日", "一", "二", "三", "四", "五", "六" };

	protected Color selectedColor = new Color(250, 100, 100);
	protected Color northColor = Color.decode("#f6f6f6"); // 控制条底色
	protected Color labelColor = new Color(55, 80, 80); // 年/月标签文字色
	protected Font labelFont = new Font("微软雅黑", Font.PLAIN, 14); // 年/月标签字体
	protected Color weekLabelColor = new Color(150, 50, 150); // 星期标签文字色
	protected Color weekendFontColor = new Color(100, 200, 100); // 周末文字色
	protected Color dateFontColor = Color.BLACK; // 日期文字色

	protected JDialog dialog;
	protected JSpinner yearSpinner;
	protected JSpinner monthSpinner;
	protected JButton[][] dayButtons = new JButton[6][7];
	protected ButtonGroup buttonGroup = new ButtonGroup();

	protected DateFormat format;
	protected Date date;
	protected String selectedDay;
	protected boolean isConfirm;

	public DateChooser() {
		this(new SimpleDateFormat("yyyy-MM-dd"));
	}

	public DateChooser(DateFormat format) {
		this(format, new Date());
	}

	public DateChooser(DateFormat format, Date date) {
		this(format, date, 1980, 2080);
	}

	public DateChooser(DateFormat format, Date date, int startYear, int lastYear) {
		this.date = date;
		this.format = format;
		this.startYear = startYear;
		this.lastYear = lastYear;
		selectedDay = getCalendar().get(Calendar.DAY_OF_MONTH) + "";

		setLayout(new BorderLayout());
		setBackground(Color.WHITE);

		JPanel northPanel = createNorthPanal();
		northPanel.setPreferredSize(new Dimension(0, 40));
		add(northPanel, BorderLayout.NORTH);

		JPanel centerPanel = createCenterPanal();
		add(centerPanel, BorderLayout.CENTER);

		JPanel southPanel = createSouthPanel();
		southPanel.setPreferredSize(new Dimension(0, 40));
		add(southPanel, java.awt.BorderLayout.SOUTH);

	}

	private JPanel createNorthPanal() {
		Calendar c = getCalendar();
		int currentYear = c.get(Calendar.YEAR);
		int currentMonth = c.get(Calendar.MONTH) + 1;

		JPanel northPanel = new JPanel();
		northPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 8));
		northPanel.setBackground(northColor);

		yearSpinner = new JSpinner(new SpinnerNumberModel(currentYear, startYear, lastYear, 1));
		yearSpinner.setEditor(new JSpinner.NumberEditor(yearSpinner, "####"));
		yearSpinner.setPreferredSize(new Dimension(60, 25));
		yearSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				updateDate(Calendar.YEAR, (Integer) yearSpinner.getValue());
			}
		});
		northPanel.add(yearSpinner);

		JLabel yearLabel = new JLabel("年");
		yearLabel.setForeground(labelColor);
		yearLabel.setFont(labelFont);
		northPanel.add(yearLabel);

		northPanel.add(Box.createHorizontalStrut(15));

		monthSpinner = new JSpinner(new SpinnerNumberModel(currentMonth, 1, 12, 1));
		monthSpinner.setEditor(new JSpinner.NumberEditor(monthSpinner, "##"));
		monthSpinner.setPreferredSize(new Dimension(60, 25));
		monthSpinner.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				updateDate(Calendar.MONTH, (Integer) monthSpinner.getValue() - 1);
			}
		});
		northPanel.add(monthSpinner);

		JLabel monthLabel = new JLabel("月");
		monthLabel.setForeground(labelColor);
		monthLabel.setFont(labelFont);
		northPanel.add(monthLabel);

		return northPanel;
	}

	private JPanel createCenterPanal() {

		JPanel centerPanel = new JPanel();
		// 设置固定字体,以免调用环境改变影响界面美观
		centerPanel.setFont(new Font("微软雅黑", Font.PLAIN, 13));
		centerPanel.setLayout(new GridLayout(7, 7));
		centerPanel.setBackground(Color.WHITE);

		for (int i = 0; i < 7; i++) {
			RolloverBackgroundButton cell = new RolloverBackgroundButton(weekStrings[i]);
			cell.clearDefaultAttribute();
			cell.setHorizontalAlignment(JLabel.RIGHT);
			cell.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			cell.setNormalForeground(weekLabelColor);
			centerPanel.add(cell);
		}

		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 7; j++) {
				final RolloverBackgroundButton numberButton = new RolloverBackgroundButton("");
				numberButton.clearDefaultAttribute();
				numberButton.setHorizontalAlignment(SwingConstants.RIGHT);
				numberButton.setNormalForeground(dateFontColor);
				numberButton.setSelectedForeground(selectedColor);
				numberButton.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						if (numberButton.getText().length() == 0) {
							return;
						}

						selectedDay = numberButton.getText();

						updateDate(Calendar.DAY_OF_MONTH, Integer.parseInt(numberButton.getText()));

						ComponentTool.clearButtonGroupSelected(buttonGroup);
						numberButton.setSelected(true);
						ComponentTool.updateButtonSelectedForeground(buttonGroup, selectedColor);
					}
				});
				if (j == 0 || j == 6) {
					numberButton.setNormalForeground(weekendFontColor);
				} else {
					numberButton.setNormalForeground(dateFontColor);
				}
				dayButtons[i][j] = numberButton;
				centerPanel.add(numberButton);
				buttonGroup.add(numberButton);
			}
		}

		return centerPanel;
	}

	private JPanel createSouthPanel() {

		JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 2));
		southPanel.setOpaque(false);

		JButton todayButton = new RolloverBackgroundButton("今天");
		todayButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				today();
			}
		});
		southPanel.add(todayButton);

		JButton cancelButton = new RolloverBackgroundButton("取消");
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				cancel();
			}
		});
		southPanel.add(cancelButton);

		JButton confirmButton = new RolloverBackgroundButton("确定");
		confirmButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				confirm();
			}
		});
		southPanel.add(confirmButton);

		return southPanel;
	}

	/**
	 * 显示日期选择对话框
	 * 
	 * @param owner
	 * @return
	 */
	public String showDateDialog(Window owner) {
		return showDateDialog(owner, null);
	}

	public String showDateDialog(Window owner, Point dialogPoint) {
		return showDateDialog(owner, dialogPoint, new Dimension(400, 250));
	}

	/**
	 * 显示日期选择对话框
	 * 
	 * @param owner
	 * @param dialogPoint
	 * @return
	 */
	public String showDateDialog(Window owner, Point dialogPoint, Dimension size) {
		if (dialog == null) {
			dialog = createDialog(owner, size);
		}
		dialog.setLocationRelativeTo(owner);
		if (dialogPoint != null) {
			dialog.setLocation(dialogPoint);
		}
		updateDayButtonsText();
		dialog.setVisible(true);
		return getDateText();
	}

	protected JDialog createDialog(Window owner, Dimension size) {
		JDialog dialog = new JDialog(owner, "日期时间选择") {
			public void setVisible(boolean b) {
				if (b) {// 此处先if还是先super顺序很重要
					isConfirm = false;
				}
				super.setVisible(b);
			}
		};
		dialog.setModal(true);
		dialog.setSize(size);
		dialog.setContentPane(this);
		dialog.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				cancel();
			}
		});
		return dialog;
	}

	/**
	 * 用户点击取消
	 */
	protected void cancel() {
		isConfirm = false;
		dialog.setVisible(false);
	}

	/**
	 * 用户点击今天
	 */
	protected void today() {
		date = new Date();
		Calendar c = getCalendar();
		yearSpinner.setValue(c.get(Calendar.YEAR));
		monthSpinner.setValue(c.get(Calendar.MONTH) + 1);
		selectedDay = c.get(Calendar.DAY_OF_MONTH) + "";
		setDate(c.getTime());
		updateDayButtonsText();
	}

	/**
	 * 用户点击确定
	 */
	protected void confirm() {
		isConfirm = true;
		dialog.setVisible(false);
	}

	protected void updateDate(int type, int value) {

		Calendar c = getCalendar();

		if (type == Calendar.MONTH) {// 处理选择的天数超出月份最大的天数情况
			int day = c.get(Calendar.DAY_OF_MONTH);
			c.set(Calendar.DAY_OF_MONTH, 1);
			c.set(type, value);
			int maxMonth_to = c.getActualMaximum(Calendar.DAY_OF_MONTH);
			if (Integer.parseInt(selectedDay) <= maxMonth_to) {// 如果当前月份所选择的天数小于即将更新的月份的最大天数
				c.set(Calendar.DAY_OF_MONTH, day);// 还原天数
			} else {// 否则
				selectedDay = "1";
			}
		} else {
			c.set(type, value);
		}

		setDate(c.getTime());

		if (type != Calendar.DAY_OF_MONTH) {
			updateDayButtonsText();
		}
	}

	protected void updateDayButtonsText() {

		Calendar c = getCalendar();
		c.set(Calendar.DAY_OF_MONTH, 1);

		int maxDayNo = c.getActualMaximum(Calendar.DAY_OF_MONTH);
		int dayNo = 2 - c.get(Calendar.DAY_OF_WEEK);

		for (int i = 0; i < 6; i++) {
			for (int j = 0; j < 7; j++) {
				String s = "";
				if (dayNo >= 1 && dayNo <= maxDayNo) {
					s = String.valueOf(dayNo);
				}
				dayButtons[i][j].setText(s);
				if (s.equals(selectedDay)) {
					ComponentTool.clearButtonGroupSelected(buttonGroup);
					dayButtons[i][j].setSelected(true);
					ComponentTool.updateButtonSelectedForeground(buttonGroup, selectedColor);
				}
				dayNo++;
			}
		}
	}

	public Dimension getDialogSize() {
		return dialog.getSize();
	}

	protected Calendar getCalendar() {
		Calendar result = Calendar.getInstance();
		result.setTime(getDate());
		return result;
	}

	/**
	 * 用户是否点击确定
	 * 
	 * @return
	 */
	public boolean isConfirm() {
		return isConfirm;
	}

	/**
	 * 获取选择的时间字符串
	 * 
	 * @return
	 */
	public String getDateText() {
		return format.format(getDate());
	}

	/**
	 * 设置默认的时间
	 * 
	 * @param date
	 */
	public void setDate(Date date) {
		this.date = date;
	}

	/**
	 * 获取选择的时间
	 * 
	 * @return
	 */
	public Date getDate() {
		return date;
	}

	// 

	public static class ComponentTool {

		public static void updateButtonSelectedForeground(ButtonGroup buttonGroup, Color selectedColor) {
			for (Enumeration<AbstractButton> enumBtn = buttonGroup.getElements(); enumBtn.hasMoreElements();) {
				RolloverBackgroundButton button = (RolloverBackgroundButton) enumBtn.nextElement();
				if (!button.isSelected()) {
					button.setSelectedForeground(null);
				} else {
					button.setSelectedForeground(selectedColor);
				}
				button.repaint();
			}
		}

		public static void clearButtonGroupSelected(ButtonGroup buttonGroup) {
			for (Enumeration<AbstractButton> button = buttonGroup.getElements(); button.hasMoreElements();) {
				button.nextElement().setSelected(false);
			}
		}
	}

	/**
	 * 鼠标悬浮和按下以及选中时能切换背景颜色/边框颜色/前景颜色的Button
	 * 
	 * @author tang
	 * @since 2014/8/23
	 * 
	 */
	public static class RolloverBackgroundButton extends JButton {

		protected Color normalBackground;// 默认无状态时背景颜色,此属性父类中已定义(background)
		protected Color pressedBackground;// 鼠标按下时背景颜色
		protected Color rolloverBackground;// 鼠标悬浮时背景颜色
		protected Color selectedBackground;// 选中时背景颜色

		protected Color normalBorderColor;// 默认无状态时边框颜色
		protected Color pressedBorderColor;// 鼠标按下时边框颜色
		protected Color rolloverBorderColor;// 鼠标悬浮时边框颜色
		protected Color selectedBorderColor;// 选中时边框颜色

		protected Color normalForeground;// 默认时前景颜色
		protected Color pressedForeground;// 鼠标按下时前景颜色
		protected Color rolloverForeground;// 鼠标悬浮时前景颜色
		protected Color selectedForeground;// 选中时前景颜色

		{
			initRolloverButton();
		}

		public RolloverBackgroundButton() {
		}

		public RolloverBackgroundButton(Icon icon) {
			super(icon);
		}

		public RolloverBackgroundButton(String text, Icon icon) {
			super(text, icon);
		}

		public RolloverBackgroundButton(String text) {
			super(text);
		}

		public RolloverBackgroundButton(Action a) {
			super(a);
		}

		private void initRolloverButton() {
			setRolloverEnabled(true);
			setBorderPainted(false);
			setContentAreaFilled(false);
			setFocusPainted(false);
			setFont(new Font(Font.DIALOG, Font.PLAIN, 14));

			setNormalBackground(new Color(216, 216, 216));
			setPressedBackground(new Color(216, 216, 216, 100));
			setNormalBorderColor(new Color(174, 174, 174));
			setRolloverBorderColor(new Color(95, 205, 245));
			setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		}

		@Override
		public void paint(Graphics g) {
			Graphics2D g2d = (Graphics2D) g;
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

			Paint oldPaint = g2d.getPaint();
			if (isSelected() && selectedBackground != null) {// 选中时
				g2d.setPaint(selectedBackground);
				g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
			} else if (getModel().isPressed() && pressedBackground != null) {// 鼠标按下时
				g2d.setPaint(pressedBackground);
				g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
			} else if (getModel().isRollover() && rolloverBackground != null) {// 鼠标悬浮时
				g2d.setPaint(rolloverBackground);
				g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
			} else if (normalBackground != null) {// 默认无状态时
				g2d.setPaint(normalBackground);
				g2d.fillRect(0, 0, getWidth(), getHeight());// 背景
			}
			g2d.setPaint(oldPaint);

			if (isSelected() && selectedForeground != null) {// 选中时
				setForeground(selectedForeground);
			} else if (getModel().isPressed() && pressedForeground != null) {// 鼠标按下时
				setForeground(pressedForeground);
			} else if (getModel().isRollover() && rolloverForeground != null) {// 鼠标悬浮时
				setForeground(rolloverForeground);
			} else if (normalForeground != null) {// 默认无状态时
				setForeground(normalForeground);
			}

			super.paint(g2d);

			if (isSelected() && selectedBorderColor != null) {// 选中时
				g2d.setPaint(selectedBorderColor);
				g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
			} else if (getModel().isPressed() && pressedBorderColor != null) {// 鼠标按下时
				g2d.setPaint(pressedBorderColor);
				g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
			} else if (getModel().isRollover() && rolloverBorderColor != null) {// 鼠标悬浮时
				g2d.setPaint(rolloverBorderColor);
				g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
			} else if (normalBorderColor != null) {// 默认无状态时
				g2d.setPaint(normalBorderColor);
				g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);// 边框
			}
			g2d.setPaint(oldPaint);
		}

		/**
		 * 清空设置的默认属性值:<br>
		 * 
		 * setNormalBackground(null);<br>
		 * setPressedBackground(null); <br>
		 * setNormalBorderColor(null); <br>
		 * setRolloverBorderColor(null);
		 * 
		 */
		public void clearDefaultAttribute() {
			setNormalBackground(null);
			setPressedBackground(null);
			setNormalBorderColor(null);
			setRolloverBorderColor(null);
		}

		public Color getNormalBackground() {
			return normalBackground;
		}

		public void setNormalBackground(Color normalBackground) {
			this.normalBackground = normalBackground;
		}

		public Color getPressedBackground() {
			return pressedBackground;
		}

		public void setPressedBackground(Color pressedBackground) {
			this.pressedBackground = pressedBackground;
		}

		public Color getRolloverBackground() {
			return rolloverBackground;
		}

		public void setRolloverBackground(Color rolloverBackground) {
			this.rolloverBackground = rolloverBackground;
		}

		public Color getNormalBorderColor() {
			return normalBorderColor;
		}

		public void setNormalBorderColor(Color normalBorderColor) {
			this.normalBorderColor = normalBorderColor;
		}

		public Color getPressedBorderColor() {
			return pressedBorderColor;
		}

		public void setPressedBorderColor(Color pressedBorderColor) {
			this.pressedBorderColor = pressedBorderColor;
		}

		public Color getRolloverBorderColor() {
			return rolloverBorderColor;
		}

		public void setRolloverBorderColor(Color rolloverBorderColor) {
			this.rolloverBorderColor = rolloverBorderColor;
		}

		public Color getPressedForeground() {
			return pressedForeground;
		}

		public void setPressedForeground(Color pressedForeground) {
			this.pressedForeground = pressedForeground;
		}

		public Color getRolloverForeground() {
			return rolloverForeground;
		}

		public void setRolloverForeground(Color rolloverForeground) {
			this.rolloverForeground = rolloverForeground;
		}

		public Color getNormalForeground() {
			return normalForeground;
		}

		public void setNormalForeground(Color normalForeground) {
			this.normalForeground = normalForeground;
		}

		public Color getSelectedBackground() {
			return selectedBackground;
		}

		public void setSelectedBackground(Color selectedBackground) {
			this.selectedBackground = selectedBackground;
		}

		public Color getSelectedBorderColor() {
			return selectedBorderColor;
		}

		public void setSelectedBorderColor(Color selectedBorderColor) {
			this.selectedBorderColor = selectedBorderColor;
		}

		public Color getSelectedForeground() {
			return selectedForeground;
		}

		public void setSelectedForeground(Color selectedForeground) {
			this.selectedForeground = selectedForeground;
		}
	}

}

运行效果图:


可以根据不同需要自行修改各种样式。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值