Java Swing JXDatePicker

时间:2013-04-19 19:13:46

标签: java swing swingx

我正在使用SwingX JXDatePicker,我无法弄清楚如何提供下一个/上一年的按钮(默认情况下它只提供下一个/上个月的按钮)。

此外,似乎不再维护SwingX:我应该使用更新的组件作为日期选择器吗?

非常感谢任何帮助/提示。 谢谢,托马斯

更新

为了澄清这个问题,我添加了一个JXDatePicker截图,并以红色突出显示下一个/上个月的按钮。 问题是:如何添加将日历带到下一年/上一年的按钮? 请注意,新按钮需要是标准组件,因为它们需要由特定的Look& amp;感觉经理(在这种情况下是Insusbtantial)。

非常感谢

enter image description here

5 个答案:

答案 0 :(得分:5)

我知道这是一个老问题,但我终于找到了答案,来自kleopatra关于SwingsLab演示的评论。

SwingsLab演示提供了一个如何基于每个组件设置自定义日历标题的示例,但这是我实际使用的代码(这是全局的;每个应用程序):

UIManager.put(CalendarHeaderHandler.uiControllerID, SpinningCalendarHeaderHandler.class.getName());
datePicker = new JXDatePicker();
datePicker.getMonthView().setZoomable(true); //this is needed for custom header

这似乎是实验性代码(尚未完全公开),因此请自担风险。希望它有所帮助。

SwingsLab Demo

答案 1 :(得分:2)

我建议使用Microba DatePicker。它具有高度可定制性,可以完全满足您的需求。

http://microba.sourceforge.net/

enter image description here enter image description here

修改

好的,我明白了。好吧,我做了一些研究,看起来你正在寻找的功能实际上并不存在于JXDatePicker中。

我发现的另一种选择是:http://sourceforge.net/projects/jdatepicker/处的JDatePicker。

主要网站:https://jdatepicker.org/

这仍然受支持,似乎有你想要的功能。

答案 2 :(得分:2)

这是几年前我把它放在一起的东西。您可以对其进行修改以满足您的需求。

enter image description here

您需要此图片才能运行主要测试:calendar icon。只需将其放在与源名相同的目录中,名称为datepicker.gif。

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Popup;
import javax.swing.PopupFactory;

public class DatePicker extends JPanel {

    private static final long serialVersionUID = 1L;

    protected boolean controlsOnTop;
    protected boolean removeOnDaySelection;

    protected Calendar currentDisplayDate;

    protected JButton prevMonth;
    protected JButton nextMonth;
    protected JButton prevYear;
    protected JButton nextYear;

    protected JTextField textField;

    protected List<ActionListener> popupListeners = 
        new ArrayList<ActionListener>();

    protected Popup popup;

    protected SimpleDateFormat dayName   = new SimpleDateFormat("d");
    protected SimpleDateFormat monthName = new SimpleDateFormat("MMMM");

    protected String iconFile = "datepicker.gif";
    protected String[] weekdayNames = 
        {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

    public DatePicker() {
        super();
        currentDisplayDate   = Calendar.getInstance();
        controlsOnTop        = true;
        removeOnDaySelection = true;
        createPanel();
    }

    public DatePicker(Calendar date) {
        super();
        setDate(date);
        controlsOnTop        = true;
        removeOnDaySelection = true;
        createPanel();
    }

    public DatePicker(int month, int day, int year) {
        super();
        setDate(month, day, year);
        controlsOnTop        = true;
        removeOnDaySelection = true;
        createPanel();
    }

    public void setDate(String date) {
        currentDisplayDate = Calendar.getInstance();
        editDate(date);
    }

    public void setDate(Calendar date) {
        currentDisplayDate = date;
        createPanel();
        validate();
        repaint();
    }

    public void setDate(int month, int day, int year) {
        currentDisplayDate = Calendar.getInstance();
        currentDisplayDate.set(expandYear(year), month - 1, day);
        createPanel();
        validate();
        repaint();
    }

    protected int expandYear(int year) {
        if (year < 100) {                   // 2 digit year
            int currentYear = Calendar.getInstance().get(Calendar.YEAR);
            int current2DigitYear = currentYear % 100;
            int currentCentury    = currentYear / 100 * 100;
            // set 2 digit year range +20 / -80 from current year
            int high2DigitYear    = (current2DigitYear + 20) % 100;
            if (year <= high2DigitYear) {
                year += currentCentury;
            }
            else {
                year += (currentCentury - 100);
            }
        }
        return year;
    }

    public void setControlsOnTop(boolean flag) {
        controlsOnTop = flag; 
        createPanel();
        validate();
        repaint();
    }

    public void setRemoveOnDaySelection(boolean flag) {
        removeOnDaySelection = flag;
    }

    public Popup getPopup(Container c) {
        if (popup == null) {
            Point p = c.getLocation();
            PopupFactory factory = PopupFactory.getSharedInstance();
            popup = factory.getPopup(c, this, p.x, p.y);
        }
        return popup;
    }

    public void popupShow(Container c) {
        getPopup(c);
        popup.show();
    }

    public void popupHide() {
        popup.hide();
    }

    public Calendar getCalendarDate() {
        return currentDisplayDate;
    }

    public Date getDate() {
        return currentDisplayDate.getTime();
    }

    public String getFormattedDate() {
        return Integer.toString(getMonth()) + "/" + 
            Integer.toString(getDay()) + "/" +
            Integer.toString(getYear());
    }

    public int getMonth() {
        return currentDisplayDate.get(Calendar.MONTH) + 1;
    }

    public int getDay() {
        return currentDisplayDate.get(Calendar.DAY_OF_MONTH);
    }

    public int getYear() {
        return currentDisplayDate.get(Calendar.YEAR);
    }

    public ImageIcon getImage() {
        return createImageIcon(iconFile, "Calendar date picker");
    }

    /* 
     * Returns an ImageIcon, or null if the path was invalid. 
     */
    protected ImageIcon createImageIcon(String path, String description) {
        URL imgURL = getClass().getResource(path);
        String fileName = imgURL.getFile().replace("bin/", "src/");
        fileName = fileName.replace("%20", " ").substring(1);
        ImageIcon icon = new ImageIcon(fileName, description);
        return icon;
    }

    protected void createPanel() {
        removeAll();
        setBorder(BorderFactory.createLineBorder(Color.black, 3));
        setFocusable(true);
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        if (controlsOnTop) {
            add(createControls());
            add(createCalendar());
        } else {
            add(createCalendar());
            add(createControls());
        }
        Dimension d = getPreferredSize();
        setPreferredSize(new Dimension(d.width, d.height + 8));
    }

    protected JPanel createControls() {        
      JPanel c = new JPanel();
      c.setBorder(BorderFactory.createRaisedBevelBorder());
      c.setFocusable(true);
      c.setLayout(new FlowLayout(FlowLayout.CENTER));

      prevYear = new JButton("<<");
      c.add(prevYear);
      prevYear.setMargin(new Insets(0,0,0,0));
      prevYear.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                addYear(-1);        
            }
      });

      prevMonth = new JButton("<");
      c.add(prevMonth);
      prevMonth.setMargin(new Insets(0,0,0,0));
      prevMonth.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                addMonth(-1);       
            }
      });


      textField = new JTextField(getFormattedDate(), 10);
      c.add(textField);
      textField.setEditable(true);
      textField.setEnabled(true);
      textField.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                editDate(textField.getText());
            }
      });

      nextMonth = new JButton(">");
      c.add(nextMonth);
      nextMonth.setMargin(new Insets(0,0,0,0));
      nextMonth.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                addMonth(+1);   
            }
      });

      nextYear = new JButton(">>");
      c.add(nextYear);
      nextYear.setMargin(new Insets(0,0,0,0));
      nextYear.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                addYear(+1);    
            }
      });

      return c;
    }

    protected JPanel createCalendar() {
        JPanel x = new JPanel();
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c  = new GridBagConstraints();

        x.setFocusable(true);
        x.setLayout(gridbag);

        String month = monthName.format(currentDisplayDate.getTime());
        String year  = Integer.toString(getYear());

        c.gridx      = 0;
        c.gridy      = 0;
        c.gridwidth  = 7;
        c.gridheight = 1;
        JLabel title = new JLabel(month + " " + year);
        x.add(title, c);
        Font font      = title.getFont();
//        Font titleFont = new Font(font.getName(), font.getStyle(),
//              font.getSize() + 2);
        Font weekFont = new Font(font.getName(), font.getStyle(),
                font.getSize() - 2);
        title.setFont(font);

        c.gridy      = 1;
        c.gridwidth  = 1;
        c.gridheight = 1;
        for (c.gridx = 0; c.gridx < 7; c.gridx++) {
            JLabel label = new JLabel(weekdayNames[c.gridx]);
            x.add(label, c);
            label.setFont(weekFont);
        }

        Calendar draw = (Calendar) currentDisplayDate.clone();
        draw.set(Calendar.DATE, 1);
        draw.add(Calendar.DATE, -draw.get(Calendar.DAY_OF_WEEK) + 1);
        int monthInt = currentDisplayDate.get(Calendar.MONTH);
//      monthInt = 0;
//      System.out.println("Current month: " + monthInt);

        c.gridwidth  = 1;
        c.gridheight = 1;
        int width    = getFontMetrics(weekFont).stringWidth(" Wed ");
        int width1   = getFontMetrics(weekFont).stringWidth("Wed");
        int height   = getFontMetrics(weekFont).getHeight() + 
                (width - width1);

        for (c.gridy = 2; c.gridy < 8; c.gridy++) {
            for (c.gridx = 0; c.gridx < 7; c.gridx++) {
                JButton dayButton;
//              System.out.print("Draw month: " + draw.get(Calendar.MONTH));
                if (draw.get(Calendar.MONTH) == monthInt) {
                    String dayString = dayName.format(draw.getTime());
                    if (draw.get(Calendar.DAY_OF_MONTH) < 10)
                        dayString = " " + dayString;
                    dayButton = new JButton(dayString);
                } else {
                    dayButton = new JButton();
                    dayButton.setEnabled(false);
                }
//              System.out.println(", day: " + dayName.format(draw.getTime()));
                x.add(dayButton, c);
                Color color = dayButton.getBackground();
                if ((draw.get(Calendar.DAY_OF_MONTH) == getDay()) &&
                        (draw.get(Calendar.MONTH) == monthInt)) { 
                    dayButton.setBackground(Color.yellow);
//                  dayButton.setFocusPainted(true);
//                  dayButton.setSelected(true);
                } else
                    dayButton.setBackground(color);
                dayButton.setFont(weekFont);
                dayButton.setFocusable(true);
                dayButton.setPreferredSize(new Dimension(width, height));
                dayButton.setMargin(new Insets(0,0,0,0));
                dayButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                        changeDay(e.getActionCommand());
                    }

                });
                draw.add(Calendar.DATE, +1);
            }
//          if (draw.get(Calendar.MONTH) != monthInt) break;
        }
        return x;
    }

    public void addMonth(int month) {
        currentDisplayDate.add(Calendar.MONTH, month);
        createPanel();
        validate();
        repaint();
    }

    public void addYear(int year) {
        currentDisplayDate.add(Calendar.YEAR, year);
        createPanel();
        validate();
        repaint();
    }

    public void editDate(String date) {
        parseDate(date);
        createPanel();
        validate();
        repaint();
    }

    protected void parseDate(String date) {
        String[] parts = date.split("/");
        if (parts.length == 3) {
            currentDisplayDate.set(Calendar.MONTH, 
                    Integer.valueOf(parts[0]) - 1);
            currentDisplayDate.set(Calendar.DAY_OF_MONTH, 
                    Integer.valueOf(parts[1]));
            currentDisplayDate.set(Calendar.YEAR, 
                    expandYear(Integer.valueOf(parts[2])));
        } else if (parts.length == 2) {
            currentDisplayDate = Calendar.getInstance();
            currentDisplayDate.set(Calendar.MONTH, 
                    Integer.valueOf(parts[0]) - 1);
            currentDisplayDate.set(Calendar.DAY_OF_MONTH, 
                    Integer.valueOf(parts[1]));
        } else {
            // invalid date
            currentDisplayDate = Calendar.getInstance();
        }
    }

    public void changeDay(String day) {
        currentDisplayDate.set(Calendar.DAY_OF_MONTH, 
                Integer.valueOf(day.trim()));
        if (removeOnDaySelection) {
            firePopupEvent(new ActionEvent(this, 1, "hide"));
            popup = null;
        } else {
            createPanel();
            validate();
            repaint();
        }
    }

    public void addPopupListener(ActionListener l) {
        popupListeners.add(l);
    }

    public void removePopupListener(ActionListener l) {
        popupListeners.remove(l);
    }

    public void firePopupEvent(ActionEvent e) {
        for (int i = popupListeners.size() - 1; i >= 0; i--) {
            ActionListener l = popupListeners.get(i);
            l.actionPerformed(e);
        }
    }

    public static void main(String[] args) {
        final JFrame frame = new JFrame("Date Picker");
        Container pane = frame.getContentPane();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(450, 250));
        pane.setLayout(new FlowLayout(FlowLayout.LEFT));
        pane.add(new JLabel("Birthdate: "));
        final JTextField testDate = new JTextField(10);
        pane.add(testDate);
        final DatePicker dp = new DatePicker();
        ImageIcon ii = dp.getImage();
//      System.out.println(ii.getIconWidth());
//      System.out.println(ii.getIconHeight());
        final JButton datePicker = new JButton(ii);
        pane.add(datePicker);
        datePicker.setPreferredSize(new Dimension(30, 24));
        datePicker.setMargin(new Insets(0,0,0,0));
        datePicker.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                dp.setDate(testDate.getText());
                dp.popupShow(datePicker);
            }
        });
        dp.addPopupListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                testDate.setText(dp.getFormattedDate());
                dp.popupHide();
            }
        });
        frame.pack();
        frame.setFocusable(true);
        frame.setResizable(true);
        frame.setVisible(true);
    }
}

答案 3 :(得分:0)

改进:

datetimePicker离按钮太远了 所以

第139行:

public Popup getPopup(Container c) {

    if (popup == null) {

        Point p = c.getLocation();

        PopupFactory factory = PopupFactory.getSharedInstance();


 // FramePrinc.Location.x ==>  public static Point Location ;  in class FramePrinc

     popup = factory.getPopup(c, this, FramePrinc.Location.x,FramePrinc.Location.y);

    }

    return popup;

}

并在操作中获取组件的位置

datePicker.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {

            //Add this Line and you will get a good result

            Location = datePickerButton.getLocationOnScreen();

            dp.setDate(testDate.getText());

            dp.popupShow(datePicker);
        }
    });

所以:

  • 创建另一个类:例如FramePrinc
  • 创建公共静态点位置
  • 在面板中添加dateTimePiker
  • 把我说的按钮动作中的行
祝你好运

Grine_Amine改进:)

答案 4 :(得分:0)

JXDatePicker缺少内置的上一个/明年的按钮是我最终没有使用该软件包的主要原因。否则,它是最好的日期选择器之一。

作为替代方案,我建议 LGoodDatePicker 。它有按钮,用于在年份中前后移动,以及用于选择任何所需年份的菜单。公平披露:我是这个项目的主要开发人员。如果符合您的需求,请告诉我。

LGoodDatePicker主页:https://github.com/LGoodDatePicker/LGoodDatePicker

发布部分中有一个工作演示(可执行jar文件),以及gitub页面上的核心功能列表。

屏幕截图如下。

enter image description here