Java Swing JXDatePicker

心已入冬 提交于 2019-11-27 07:01:31

问题


I'm using SwingX JXDatePicker and I can't figure out how to provide next/previous year buttons (as by default it only provides next/previous month buttons).

Also, it seems that SwingX is not maintained anymore: should I be using a more recent component as date picker?

Any help/hint would be greatly appreciated. Thanks, Thomas

UPDATE:

To clarify the question, I added a JXDatePicker screenshot and highlighted in red the next/previous month buttons. The questions is thus: how to add buttons that will bring the calendar to next/previous year? Please note that the new buttons need to be standard components as they need to be rendered by a particular Look & Feel manager (Insusbtantial in this case).

Many thanks


回答1:


I would recommend using Microba DatePicker. It's highly customizable and does exactly what you want.

http://microba.sourceforge.net/

Edit:

Ok I see. Well I did some research and it seems the function you are looking for is actually not present in JXDatePicker.

A different alternative I found is: JDatePicker at http://sourceforge.net/projects/jdatepicker/.

Main website: https://jdatepicker.org/

This is still supported and seems to have the function you want.




回答2:


I know this is an old question, but I finally found the answer here, from kleopatra's comment about SwingsLab demo.

The SwingsLab demo provides an example of how to set a custom calendar header on a per-component basis, but this is the code I actually used (this is global; per-application):

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

This seems to be experimental code (not fully public yet), so use at own risk. Hope it helps.




回答3:


This is something I put together a few years ago. You can modify it to meet your needs.

You'll need this image to run the main test:

. Just put it in the same directory as the source with the name 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);
    }
}



回答4:


improvement :

the datetimePicker is too far from the button so

at line 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;

}

and inside the action you get the location of the component

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);
        }
    });

So :

  • create another class : for example FramePrinc
  • create public static Point Location
  • add you dateTimePiker inside a panel
  • put the line that i said inside the button action

good luck

Grine_Amine Improvement :)




回答5:


The lack of built-in previous/next year buttons in JXDatePicker is the main reason I did not end up using that package for my software. Otherwise, it's one of the better date pickers that is out there.

As an alternative, I'd recommend LGoodDatePicker. It has buttons for going back and forward on the year, plus a menu for selecting any desired year. Fair disclosure: I'm the primary developer on this project. Please let me know if it serves your needs.

LGoodDatePicker home page: https://github.com/LGoodDatePicker/LGoodDatePicker

There is a working demo (an executable jar file) in the release section, and a list of core features on the gitub page.

Screenshots are below.



来源:https://stackoverflow.com/questions/16111943/java-swing-jxdatepicker

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!