我正在使用SwingX JXDatePicker,我无法弄清楚如何提供下一个/上一年的按钮(默认情况下它只提供下一个/上个月的按钮)。
此外,似乎不再维护SwingX:我应该使用更新的组件作为日期选择器吗?
非常感谢任何帮助/提示。 谢谢,托马斯
更新
为了澄清这个问题,我添加了一个JXDatePicker截图,并以红色突出显示下一个/上个月的按钮。 问题是:如何添加将日历带到下一年/上一年的按钮? 请注意,新按钮需要是标准组件,因为它们需要由特定的Look& amp;感觉经理(在这种情况下是Insusbtantial)。
非常感谢
答案 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
这似乎是实验性代码(尚未完全公开),因此请自担风险。希望它有所帮助。
答案 1 :(得分:2)
我建议使用Microba DatePicker。它具有高度可定制性,可以完全满足您的需求。
http://microba.sourceforge.net/
修改强>
好的,我明白了。好吧,我做了一些研究,看起来你正在寻找的功能实际上并不存在于JXDatePicker中。
我发现的另一种选择是:http://sourceforge.net/projects/jdatepicker/处的JDatePicker。
这仍然受支持,似乎有你想要的功能。
答案 2 :(得分:2)
这是几年前我把它放在一起的东西。您可以对其进行修改以满足您的需求。
您需要此图片才能运行主要测试:。只需将其放在与源名相同的目录中,名称为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);
}
});
所以:
Grine_Amine改进:)
答案 4 :(得分:0)
JXDatePicker缺少内置的上一个/明年的按钮是我最终没有使用该软件包的主要原因。否则,它是最好的日期选择器之一。
作为替代方案,我建议 LGoodDatePicker 。它有按钮,用于在年份中前后移动,以及用于选择任何所需年份的菜单。公平披露:我是这个项目的主要开发人员。如果符合您的需求,请告诉我。
LGoodDatePicker主页:https://github.com/LGoodDatePicker/LGoodDatePicker
发布部分中有一个工作演示(可执行jar文件),以及gitub页面上的核心功能列表。
屏幕截图如下。