Java Swing JXDatePicker

Posted

技术标签:

【中文标题】Java Swing JXDatePicker【英文标题】: 【发布时间】:2013-04-13 06:41:57 【问题描述】:

我正在使用 SwingX JXDatePicker,但我不知道如何提供下一个/上一年的按钮(默认情况下它只提供下一个/上一个月的按钮)。

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

任何帮助/提示将不胜感激。 谢谢,托马斯

更新:

为了澄清这个问题,我添加了一个 JXDatePicker 屏幕截图,并以红色突出显示了下个月/上个月按钮。 因此,问题是:如何添加将日历带到下一年/上一年的按钮? 请注意,新按钮必须是标准组件,因为它们需要由特定的外观管理器呈现(在本例中为不确定)。

非常感谢

【问题讨论】:

查看this 问题以获取最新替代方案列表。我建议尝试其中一些。 维护 - 当前版本为 1.6.5-1,但不明白你在追求什么:你到底想要什么?为什么swingx demos(项目页面上的webstartable链接)中描述的自定义没有帮助) @MrD 为什么传播不相关的链接?那是关于一个完全不相关的问题...... 感谢您的提示。 SwingX 演示没有给出带有“下/上一年”按钮的示例(它只有标准的下/上个月)。我错过了什么?谢谢 【参考方案1】:

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

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

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

这似乎是实验性代码(尚未完全公开),因此使用风险自负。希望对您有所帮助。

【讨论】:

很好,有人真的看了演示 :-) @Radiace Wei Q Ong 感谢您的发帖,但使用您的代码不会显示图片中显示的年份。我也有同样的要求。 @Syed Muhammad Mubashir 它对我有用。也许试试 SwingsLab 演示中的代码?图片来自演示。【参考方案2】:

我会推荐使用 Microba DatePicker。它高度可定制,完全符合您的要求。

http://microba.sourceforge.net/

编辑:

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

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

主站:https://jdatepicker.org/

这个还是支持的,好像有你想要的功能。

【讨论】:

不幸的是,这个组件不再维护(过去 5 年没有发布):这对我们来说太冒险了,因为 Java / Swing 的未来版本可能会破坏它并且不会被修复.. . @Omid 你能告诉我如何在 Swing 组件中添加它并拖动到 jframe 中,我使用 JPallete Manager 添加但这个组件不会拖动到 jframe 中。 我在唱 Net Beans 7.1,这是否与 NeBeans 7.1 和 Swing 框架兼容。【参考方案3】:

这是我几年前整理的。您可以对其进行修改以满足您的需求。

您将需要此图像来运行主要测试:。只需将其放在与名称为 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】:

改进:

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 改进 :)

【讨论】:

【参考方案5】:

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

作为替代方案,我推荐 LGoodDatePicker。它具有用于在年份上前后移动的按钮,以及用于选择任何所需年份的菜单。公平披露:我是这个项目的主要开发者。如果它满足您的需求,请告诉我。

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

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

截图如下。

【讨论】:

以上是关于Java Swing JXDatePicker的主要内容,如果未能解决你的问题,请参考以下文章

java的swing组件的使用

java awt和swing包自带吗

java里的swing是啥意思,为啥取名swing

如果要在java中使用文件处理一定要使用java.swing包

java swing怎么清空表单

java swing 实现打开文件,java swing Dialog