Swing日期時間選擇框控件

openkk 12年前發布 | 125K 次閱讀 Swing Java開發

最近做一個Swing軟件,其中要用到日期時間選擇器(DateChooser),但是Swing中沒有現成的日期時間選擇器可用,于是在網上搜索了一下,找了一個比較靠譜的例子,因為任務比較緊,所以沒有時間細致地美化,自己修改了幾處,增加了一些注釋,增加了幾個功能(如:增加了確定、取消按鈕;添加了取消時JButton的Text恢復選擇前的日期時間;增加了得到當前日期時間格式化器等),現在放出來,歡迎有時間的同學繼續完善。

先上一張效果圖

Swing日期時間選擇框控件

代碼如下:

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.Frame;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

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.SpinnerNumberModel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.border.LineBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener;

/*

  • YouAreStupid 收集網上靠譜的例子,修改后的Swing日期
  • 時間選擇器,因為修改時間匆忙,希望有時間的朋友繼續改進。
  • 例子原作者:zjw
  • 修改/完善:YouAreStupid */ public class DateChooserJButton extends JButton {

    private DateChooser dateChooser = null; private String preLabel = ""; private String originalText = null; private SimpleDateFormat sdf = null;

    public DateChooserJButton() {

     this(getNowDate());
    

    }

    public DateChooserJButton(String dateString) {

     this();
     setText(getDefaultDateFormat(), dateString);
     //保存原始是日期時間
     initOriginalText(dateString);
    

    }

    public DateChooserJButton(SimpleDateFormat df, String dateString) {

     this();
     setText(df, dateString);
    
     //記憶當前的日期格式化器
     this.sdf = df;
    
     //記憶原始日期時間
     Date originalDate = null;
     try {
         originalDate = df.parse(dateString);
     } catch (ParseException ex) {
         originalDate = getNowDate();
     }
     initOriginalText(originalDate);
    

    }

    public DateChooserJButton(Date date) {

     this("", date);
     //記憶原始日期時間
     initOriginalText(date);
    

    }

    public DateChooserJButton(String preLabel, Date date) {

     if (preLabel != null) {
         this.preLabel = preLabel;
     }
     setDate(date);
     //記憶原始是日期時間
     initOriginalText(date);
    
     setBorder(null);
     setCursor(new Cursor(Cursor.HAND_CURSOR));
     super.addActionListener(new ActionListener() {
    
         @Override
         public void actionPerformed(ActionEvent e) {
             if (dateChooser == null) {
                 dateChooser = new DateChooser();
             }
             Point p = getLocationOnScreen();
             p.y = p.y + 30;
             dateChooser.showDateChooser(p);
         }
     });
    

    }

    private static Date getNowDate() {

     return Calendar.getInstance().getTime();
    

    }

    private static SimpleDateFormat getDefaultDateFormat() {

     return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    

    }

    /**

    • 得到當前使用的日期格式化器
    • @return 日期格式化器 */ public SimpleDateFormat getCurrentSimpleDateFormat(){ if(this.sdf != null){
       return sdf;
      
      }else{
       return getDefaultDateFormat();
      
      } }
//保存原始是日期時間
private void initOriginalText(String dateString) {
    this.originalText = dateString;
}

//保存原始是日期時間
private void initOriginalText(Date date) {
    this.originalText = preLabel + getDefaultDateFormat().format(date);
}

/** 
 * 得到當前記憶的原始日期時間
 * @return 當前記憶的原始日期時間(未修改前的日期時間)
 */
public String getOriginalText() {
    return originalText;
}

// 覆蓋父類的方法
@Override
public void setText(String s) {
    Date date;
    try {
        date = getDefaultDateFormat().parse(s);
    } catch (ParseException e) {
        date = getNowDate();
    }
    setDate(date);
}

public void setText(SimpleDateFormat df, String s) {
    Date date;
    try {
        date = df.parse(s);
    } catch (ParseException e) {
        date = getNowDate();
    }
    setDate(date);
}

public void setDate(Date date) {
    super.setText(preLabel + getDefaultDateFormat().format(date));
}

public Date getDate() {
    String dateString = getText().substring(preLabel.length());
    try {
        SimpleDateFormat currentSdf = getCurrentSimpleDateFormat();
        return currentSdf.parse(dateString);
    } catch (ParseException e) {
        return getNowDate();
    }
}

/**  
 * 覆蓋父類的方法使之無效
 * @param listener 響應監聽器
 */
@Override
public void addActionListener(ActionListener listener) {
}

/**
 * 內部類,主要是定義一個JPanel,然后把日歷相關的所有內容填入本JPanel,
 * 然后再創建一個JDialog,把本內部類定義的JPanel放入JDialog的內容區
 */
private class DateChooser extends JPanel implements ActionListener, ChangeListener {

    int startYear = 1980; // 默認【最小】顯示年份
    int lastYear = 2050; // 默認【最大】顯示年份
    int width = 390; // 界面寬度
    int height = 210; // 界面高度
    Color backGroundColor = Color.gray; // 底色
    // 月歷表格配色----------------//
    Color palletTableColor = Color.white; // 日歷表底色
    Color todayBackColor = Color.orange; // 今天背景色
    Color weekFontColor = Color.blue; // 星期文字色
    Color dateFontColor = Color.black; // 日期文字色
    Color weekendFontColor = Color.red; // 周末文字色
    // 控制條配色------------------//
    Color controlLineColor = Color.pink; // 控制條底色
    Color controlTextColor = Color.white; // 控制條標簽文字色
    Color rbFontColor = Color.white; // RoundBox文字色
    Color rbBorderColor = Color.red; // RoundBox邊框色
    Color rbButtonColor = Color.pink; // RoundBox按鈕色
    Color rbBtFontColor = Color.red; // RoundBox按鈕文字色
    /** 點擊DateChooserButton時彈出的對話框,日歷內容在這個對話框內 */
    JDialog dialog;
    JSpinner yearSpin;
    JSpinner monthSpin;
    JSpinner daySpin;
    JSpinner hourSpin;
    JSpinner minuteSpin;
    JSpinner secondSpin;
    JButton[][] daysButton = new JButton[6][7];

    DateChooser() {

        setLayout(new BorderLayout());
        setBorder(new LineBorder(backGroundColor, 2));
        setBackground(backGroundColor);

        JPanel topYearAndMonth = createYearAndMonthPanal();
        add(topYearAndMonth, BorderLayout.NORTH);
        JPanel centerWeekAndDay = createWeekAndDayPanal();
        add(centerWeekAndDay, BorderLayout.CENTER);
        JPanel buttonBarPanel = createButtonBarPanel();
        this.add(buttonBarPanel, java.awt.BorderLayout.SOUTH);
    }

    private JPanel createYearAndMonthPanal() {
        Calendar c = getCalendar();
        int currentYear = c.get(Calendar.YEAR);
        int currentMonth = c.get(Calendar.MONTH) + 1;
        int currentHour = c.get(Calendar.HOUR_OF_DAY);
        int currentMinute = c.get(Calendar.MINUTE);
        int currentSecond = c.get(Calendar.SECOND);

        JPanel result = new JPanel();
        result.setLayout(new FlowLayout());
        result.setBackground(controlLineColor);

        yearSpin = new JSpinner(new SpinnerNumberModel(currentYear, startYear, lastYear, 1));
        yearSpin.setPreferredSize(new Dimension(48, 20));
        yearSpin.setName("Year");
        yearSpin.setEditor(new JSpinner.NumberEditor(yearSpin, "####"));
        yearSpin.addChangeListener(this);
        result.add(yearSpin);

        JLabel yearLabel = new JLabel("年");
        yearLabel.setForeground(controlTextColor);
        result.add(yearLabel);

        monthSpin = new JSpinner(new SpinnerNumberModel(currentMonth, 1, 12, 1));
        monthSpin.setPreferredSize(new Dimension(35, 20));
        monthSpin.setName("Month");
        monthSpin.addChangeListener(this);
        result.add(monthSpin);

        JLabel monthLabel = new JLabel("月");
        monthLabel.setForeground(controlTextColor);
        result.add(monthLabel);

        //如果這里要能夠選擇,會要判斷很多東西,比如每個月分別由多少日,以及閏年問題.所以,就干脆把Enable設為false
        daySpin = new JSpinner(new SpinnerNumberModel(currentMonth, 1, 31, 1));
        daySpin.setPreferredSize(new Dimension(35, 20));
        daySpin.setName("Day");
        daySpin.addChangeListener(this);
        daySpin.setEnabled(false);
        daySpin.setToolTipText("請下下面的日歷面板中進行選擇哪一天!");
        result.add(daySpin);

        JLabel dayLabel = new JLabel("日");
        dayLabel.setForeground(controlTextColor);
        result.add(dayLabel);

        hourSpin = new JSpinner(new SpinnerNumberModel(currentHour, 0, 23, 1));
        hourSpin.setPreferredSize(new Dimension(35, 20));
        hourSpin.setName("Hour");
        hourSpin.addChangeListener(this);
        result.add(hourSpin);

        JLabel hourLabel = new JLabel("時");
        hourLabel.setForeground(controlTextColor);
        result.add(hourLabel);

        minuteSpin = new JSpinner(new SpinnerNumberModel(currentMinute, 0, 59, 1));
        minuteSpin.setPreferredSize(new Dimension(35, 20));
        minuteSpin.setName("Minute");
        minuteSpin.addChangeListener(this);
        result.add(minuteSpin);

        JLabel minuteLabel = new JLabel("分");
        hourLabel.setForeground(controlTextColor);
        result.add(minuteLabel);

        secondSpin = new JSpinner(new SpinnerNumberModel(currentSecond, 0, 59, 1));
        secondSpin.setPreferredSize(new Dimension(35, 20));
        secondSpin.setName("Second");
        secondSpin.addChangeListener(this);
        result.add(secondSpin);

        JLabel secondLabel = new JLabel("秒");
        hourLabel.setForeground(controlTextColor);
        result.add(secondLabel);

        return result;
    }

    private JPanel createWeekAndDayPanal() {
        String colname[] = {"日", "一", "二", "三", "四", "五", "六"};
        JPanel result = new JPanel();
        // 設置固定字體,以免調用環境改變影響界面美觀
        result.setFont(new Font("宋體", Font.PLAIN, 12));
        result.setLayout(new GridLayout(7, 7));
        result.setBackground(Color.white);
        JLabel cell;

        for (int i = 0; i < 7; i++) {
            cell = new JLabel(colname[i]);
            cell.setHorizontalAlignment(JLabel.RIGHT);
            if (i == 0 || i == 6) {
                cell.setForeground(weekendFontColor);
            } else {
                cell.setForeground(weekFontColor);
            }
            result.add(cell);
        }

        int actionCommandId = 0;
        for (int i = 0; i < 6; i++) {
            for (int j = 0; j < 7; j++) {
                JButton numberButton = new JButton();
                numberButton.setBorder(null);
                numberButton.setHorizontalAlignment(SwingConstants.RIGHT);
                numberButton.setActionCommand(String.valueOf(actionCommandId));
                numberButton.addActionListener(this);
                numberButton.setBackground(palletTableColor);
                numberButton.setForeground(dateFontColor);
                if (j == 0 || j == 6) {
                    numberButton.setForeground(weekendFontColor);
                } else {
                    numberButton.setForeground(dateFontColor);
                }
                daysButton[i][j] = numberButton;
                result.add(numberButton);
                actionCommandId++;
            }
        }

        return result;
    }

    /** 得到DateChooserButton的當前text,本方法是為按鈕事件匿名類準備的。 */
    public String getTextOfDateChooserButton() {
        return getText();
    }

    /** 恢復DateChooserButton的原始日期時間text,本方法是為按鈕事件匿名類準備的。 */
    public void restoreTheOriginalDate() {
        String originalText = getOriginalText();
        setText(originalText);
    }

    private JPanel createButtonBarPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new java.awt.GridLayout(1, 2));

        JButton ok = new JButton("確定");
        ok.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //記憶原始日期時間
                initOriginalText(getTextOfDateChooserButton());
                //隱藏日歷對話框
                dialog.setVisible(false);
            }
        });
        panel.add(ok);

        JButton cancel = new JButton("取消");
        cancel.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                //恢復原始的日期時間
                restoreTheOriginalDate();
                //隱藏日歷對話框
                dialog.setVisible(false);
            }
        });

        panel.add(cancel);
        return panel;
    }

    private JDialog createDialog(Frame owner) {
        JDialog result = new JDialog(owner, "日期時間選擇", true);
        result.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
        result.getContentPane().add(this, BorderLayout.CENTER);
        result.pack();
        result.setSize(width, height);
        return result;
    }

    void showDateChooser(Point position) {
        Frame owner = (Frame) SwingUtilities.getWindowAncestor(DateChooserJButton.this);
        if (dialog == null || dialog.getOwner() != owner) {
            dialog = createDialog(owner);
        }
        dialog.setLocation(getAppropriateLocation(owner, position));
        flushWeekAndDay();
        dialog.setVisible(true);
    }

    Point getAppropriateLocation(Frame owner, Point position) {
        Point result = new Point(position);
        Point p = owner.getLocation();
        int offsetX = (position.x + width) - (p.x + owner.getWidth());
        int offsetY = (position.y + height) - (p.y + owner.getHeight());

        if (offsetX > 0) {
            result.x -= offsetX;
        }

        if (offsetY > 0) {
            result.y -= offsetY;
        }

        return result;
    }

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

    private int getSelectedYear() {
        return ((Integer) yearSpin.getValue()).intValue();
    }

    private int getSelectedMonth() {
        return ((Integer) monthSpin.getValue()).intValue();
    }

    private int getSelectedHour() {
        return ((Integer) hourSpin.getValue()).intValue();
    }

    private int getSelectedMinite() {
        return ((Integer) minuteSpin.getValue()).intValue();
    }

    private int getSelectedSecond() {
        return ((Integer) secondSpin.getValue()).intValue();
    }

    private void dayColorUpdate(boolean isOldDay) {
        Calendar c = getCalendar();
        int day = c.get(Calendar.DAY_OF_MONTH);
        c.set(Calendar.DAY_OF_MONTH, 1);
        int actionCommandId = day - 2 + c.get(Calendar.DAY_OF_WEEK);
        int i = actionCommandId / 7;
        int j = actionCommandId % 7;
        if (isOldDay) {
            daysButton[i][j].setForeground(dateFontColor);
        } else {
            daysButton[i][j].setForeground(todayBackColor);
        }
    }

    private void flushWeekAndDay() {
        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);
                }
                daysButton[i][j].setText(s);
                dayNo++;
            }
        }
        dayColorUpdate(false);
    }

    /**
     * 選擇日期時的響應事件
     */
    @Override
    public void stateChanged(ChangeEvent e) {
        JSpinner source = (JSpinner) e.getSource();
        Calendar c = getCalendar();
        if (source.getName().equals("Hour")) {
            c.set(Calendar.HOUR_OF_DAY, getSelectedHour());
            setDate(c.getTime());
            return;
        }
        if (source.getName().equals("Minute")) {
            c.set(Calendar.MINUTE, getSelectedMinite());
            setDate(c.getTime());
            return;
        }
        if (source.getName().equals("Second")) {
            c.set(Calendar.SECOND, getSelectedSecond());
            setDate(c.getTime());
            return;
        }

        dayColorUpdate(true);

        if (source.getName().equals("Year")) {
            c.set(Calendar.YEAR, getSelectedYear());
        } else if (source.getName().equals("Month")) {
            c.set(Calendar.MONTH, getSelectedMonth() - 1);
        }
        setDate(c.getTime());
        flushWeekAndDay();
    }

    /**
     * 選擇日期時的響應事件
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        JButton source = (JButton) e.getSource();
        if (source.getText().length() == 0) {
            return;
        }
        dayColorUpdate(true);
        source.setForeground(todayBackColor);
        int newDay = Integer.parseInt(source.getText());
        Calendar c = getCalendar();
        c.set(Calendar.DAY_OF_MONTH, newDay);
        setDate(c.getTime());
        //把daySpin中的值也變了
        daySpin.setValue(Integer.valueOf(newDay));
    }
}

/**
 * 測試方法
 */
public static void main(String[] args) {
    JFrame mainFrame = new JFrame("測試");
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setSize(300, 300);
    mainFrame.setLayout(new java.awt.BorderLayout());
    mainFrame.add(new DateChooserJButton(), java.awt.BorderLayout.CENTER);

    Toolkit kit = Toolkit.getDefaultToolkit();
    Dimension screenSize = kit.getScreenSize();
    int width = (int) screenSize.getWidth();
    int height = (int) screenSize.getHeight();
    int w = mainFrame.getWidth();
    int h = mainFrame.getHeight();
    mainFrame.setLocation((width - w) / 2, (height - h) / 2);

    mainFrame.setVisible(true);
}

}</pre>

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!