Java Swing JXDatePicker

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

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

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

更新:

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

非常感谢

在此处输入图像描述

我建议使用Microba DatePicker。 它是高度可定制的,完全符合您的要求。

http://microba.sourceforge.net/

在此处输入图像描述在此处输入图像描述

编辑:

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

我找到的另一种选择是: http ://sourceforge.net/projects/jdatepicker/上的JDatePicker。

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

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

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

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

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

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

SwingsLab演示

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

在此处输入图像描述

您需要此图像才能运行主测试: 日历图标 。 只需将其放在与源名称为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 popupListeners = new ArrayList(); 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, px, py); } 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); } } 

改进:

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

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

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

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

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

屏幕截图如下。

在此处输入图像描述