用Java Swing实现的自定义日历组件

主要是用JTextField、JComboBox、JDialog等组件组合而成的日历组件,先贴下效果图。


程序并不复杂,主要是点击了文本框旁边的按钮后会弹出一个没有标题栏的对话框,用以装载日历组件。

不多作解释了,直接看源代码吧

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.Calendar;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.plaf.ButtonUI;
import javax.swing.plaf.ComboBoxUI;

public class DateField extends JPanel
{
	private JTextField tfDate;
	private JButton button;
	private JDialog dlg;
	private JPanel paCalendar;
	private boolean show;
	private JComboBox cboYear;
	private JComboBox cboMonth;
	private JLabel[] lbls = new JLabel[7];
	private JToggleButton[] toggles = new JToggleButton[42];
	private Border border;
	private Color bgColor;
	private int width = 150, height = 25;
	private int year;
	private int month;
	private int date;
	private int dayOfWeek;
	private String[] week = { "日", "一", "二", "三", "四", "五", "六" };

	public DateField()
	{
		year = Calendar.getInstance().get(Calendar.YEAR);
		month = Calendar.getInstance().get(Calendar.MONTH) + 1;
		date = Calendar.getInstance().get(Calendar.DATE);
		dayOfWeek = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
		initUI();
		initDateDialog();
		updateField();
	}

	private void initUI()
	{
		tfDate = new JTextField();
		tfDate.setEditable(false);
		tfDate.setBackground(Color.WHITE);
		border = tfDate.getBorder();
		tfDate.setBorder(null);

		button = new JButton();
		button.setPreferredSize(new Dimension(height, height));
		button.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if (show == false)
				{
					dlg.setLocation(DateField.this.getLocationOnScreen().x, DateField.this.getLocationOnScreen().y + DateField.this.height);
					dlg.setAlwaysOnTop(true);
					dlg.setVisible(true);
				} else
				{
					dlg.dispose();
				}
				updateField();
				show = !show;
			}
		});

		this.bgColor = this.getBackground();

		this.setOpaque(false);
		this.setLayout(new BorderLayout(0, 0));
		this.setBorder(border);
		this.add(tfDate, BorderLayout.CENTER);
		this.add(button, BorderLayout.EAST);
	}

	private void initDateDialog()
	{
		dlg = new JDialog();
		dlg.setUndecorated(true);
		paCalendar = new JPanel(new BorderLayout());
		paCalendar.setBorder(this.border);
		paCalendar.setBackground(this.bgColor);

		int borderWidth = 3;
		// 初始化两个下拉组件用于年和月的选择
		JPanel paHeader = new JPanel(new GridLayout(1, 2, borderWidth, borderWidth));
		paHeader.setOpaque(false);
		paHeader.setPreferredSize(new Dimension(this.width, this.height + borderWidth));
		paHeader.setBorder(BorderFactory.createEmptyBorder(borderWidth, borderWidth, borderWidth, borderWidth));
		paHeader.add(cboYear = new JComboBox());
		paHeader.add(cboMonth = new JComboBox());
		initYearModel();
		initMonthModel();
		paCalendar.add(paHeader, BorderLayout.NORTH);

		// 初始化日期组件
		JPanel paDay = new JPanel();
		paDay.setOpaque(false);
		paDay.setPreferredSize(new Dimension(this.height * 7, this.height * 7));
		initDate(paDay);
		paCalendar.add(paDay, BorderLayout.CENTER);

		dlg.setContentPane(paCalendar);
		dlg.pack();
		dlg.addWindowFocusListener(new WindowAdapter()
		{
			public void windowLostFocus(WindowEvent e)
			{
				dlg.dispose();
			}
		});
	}

	private void initYearModel()
	{
		for (int y = 1970; y < 2033; y++)
			cboYear.addItem(y);
		cboYear.setSelectedItem(year);
		cboYear.addItemListener(new ItemListener()
		{
			public void itemStateChanged(ItemEvent e)
			{
				year = Integer.parseInt(cboYear.getSelectedItem().toString());
				updateComponent();
			}

		});
	}

	private void initMonthModel()
	{
		for (int m = 1; m <= 12; m++)
			cboMonth.addItem(m);
		cboMonth.setSelectedItem(month);
		cboMonth.addItemListener(new ItemListener()
		{

			public void itemStateChanged(ItemEvent e)
			{
				month = Integer.parseInt(cboMonth.getSelectedItem().toString());
				updateComponent();
			}
		});
	}

	private void initDate(JPanel pa)
	{
		pa.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
		// 显示日历的标签栏
		for (int i = 0; i < week.length; i++)
		{
			lbls[i] = new JLabel(week[i]);
			lbls[i].setHorizontalAlignment(SwingConstants.CENTER);
			lbls[i].setOpaque(true);
			lbls[i].setBackground(Color.WHITE);
			lbls[i].setPreferredSize(new Dimension(this.height, this.height));
			pa.add(lbls[i]);
		}
		// 加载日历按钮
		ButtonGroup group = new ButtonGroup();
		for (int i = 0; i < 42; i++)
		{
			toggles[i] = new JToggleButton();
			toggles[i].setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			toggles[i].setPreferredSize(new Dimension(this.height, this.height));
			toggles[i].addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					date = Integer.parseInt(((JToggleButton) e.getSource()).getText().toString());
					dlg.dispose();
					updateField();
				}
			});
			group.add(toggles[i]);
			pa.add(toggles[i]);
		}
		updateComponent();
	}

	private void updateComponent()
	{
		if (cboYear == null || cboMonth == null)
			return;
		Calendar cal = Calendar.getInstance();
		cal.set(year, month - 1, 1);
		// 根据当月的第一天是星期几来判断日历按钮的数字该从第几个按钮开始显示
		int off = cal.get(Calendar.DAY_OF_WEEK) - 1;
		// 计算当月总共有几天
		int end = 30;
		if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
			end = 31;
		if (month == 2)
		{
			if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
				end = 29;
			else
				end = 28;
		}
		for (int i = 0; i < 42; i++)
		{
			if (i >= off && i <= end + off - 1)
			{
				int day = i - off + 1;
				toggles[i].setText(day + "");
				toggles[i].setEnabled(true);
			} else
			{
				toggles[i].setText("");
				toggles[i].setEnabled(false);
			}
		}
		// 使当天的按钮呈现被按下的效果
		int day = Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + off - 1;
		toggles[day].setSelected(true);
	}

	// 更新文本框内的文字
	private void updateField()
	{
		StringBuilder builder = new StringBuilder();
		builder.append(this.year + "年");
		builder.append(this.month + "月");
		builder.append(this.date + "日");
		Calendar cal = Calendar.getInstance();
		cal.set(this.year, this.month - 1, this.date);
		builder.append(" 星期" + week[cal.get(Calendar.DAY_OF_WEEK) - 1]);
		tfDate.setText(builder.toString());
	}

	public Dimension getPreferredSize()
	{
		return new Dimension(this.width, this.height);
	}

	public void setPreferredSize(Dimension preferredSize)
	{
		super.setPreferredSize(preferredSize);
		this.width = (int) preferredSize.getWidth();
		this.height = (int) preferredSize.getHeight();
	}

	public void setBackground(Color bg)
	{
		super.setBackground(bg);
		this.bgColor = bg;
	}

	public void setBorder(Border border)
	{
		super.setBorder(border);
		if (paCalendar != null)
			paCalendar.setBorder(border);
	}

	public void setButtonUI(String clzUIName)
	{
		try
		{
			button.setUI((ButtonUI) Class.forName(clzUIName).newInstance());
		}
		catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
		{
			e.printStackTrace();
		}
	}

	public void setDateButtonUI(String clzUIName)
	{
		try
		{
			for (int i = 0; i < 42; i++)
				toggles[i].setUI((ButtonUI) Class.forName(clzUIName).newInstance());
		}
		catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void setComboBoxUI(String clzUIName)
	{
		try
		{
			cboYear.setUI((ComboBoxUI) Class.forName(clzUIName).newInstance());
			cboMonth.setUI((ComboBoxUI) Class.forName(clzUIName).newInstance());
		}
		catch (InstantiationException | IllegalAccessException | ClassNotFoundException e)
		{
			e.printStackTrace();
		}

	}

	public void setLableColor(Color fg, Color bg)
	{
		for (int i = 0; i < lbls.length; i++)
		{
			lbls[i].setForeground(fg);
			lbls[i].setBackground(bg);
		}
	}

	public void setIcon(Image icon)
	{
		button.setIcon(new ImageIcon(icon));
	}

	public int getYear()
	{
		return this.year;
	}

	public int getMonth()
	{
		return this.month;
	}

	public int getDateOfWeek()
	{
		return this.date;
	}

	public Date getDate()
	{
		Calendar cal = Calendar.getInstance();
		cal.set(this.year, this.month, this.date);
		return cal.getTime();
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Greentea107

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

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

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

打赏作者

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

抵扣说明:

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

余额充值