1

我有一个问题,它已经困扰我很长时间了......

我有一个带有 gridlayout(6,7) 的 JPanel,我的问题是正确更新数据。我正在制作一个简单的日历软件,当然我正在使用日历。问题是当我更改日历对象 MONTH 字段并将新月份数据获取到此 JPanel 网格布局但数据未正确显示时。

我是在计算我的数据字段不正确还是应该如何更新 MONTH 字段。我试过 set(int,int,int),add(CalendarObject.MONTH,+/-1),roll(CalendarObject.MONTH,true/false)。

button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                cal.set(cal.YEAR,cal.MONTH-1,1);
                cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK));
                Component[] comps = JavaCalendar.panel.getComponents();
                for (Component comp : comps) {
                    JPanel p = (JPanel) comp;
                    JLabel c = (JLabel) p.getComponent(0);
                    c.setText(day.format(cal.getTime()));
                    cal.add(Calendar.DATE, +1);
                }

        }
    });

是因为 for 循环大约进行了 42 次并且它更新每个字段并每次调用 add() ......?数据更新有点不正确...示例 5 月 1 日是 Wensday,6 月 1 日是星期六,但是当调用此 actionPerfomed() 时,它显示 6 月 1 日是星期日。

SSCE 代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Calendar;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.*;
import java.text.SimpleDateFormat;
import java.util.Locale;

public class JavaCalendar extends JFrame {
private Calendar cal;
public static JPanel paneeli;

public static SimpleDateFormat month = new SimpleDateFormat("M");
private SimpleDateFormat year = new SimpleDateFormat("y");
private SimpleDateFormat day = new SimpleDateFormat("d");
private SimpleDateFormat Day = new SimpleDateFormat("E");

public JavaCalendar() {
    super("JavaCalendar");
    cal = Calendar.getInstance(Locale.getDefault());
    cal.setFirstDayOfWeek(Calendar.MONDAY);
    setSize(500,400);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(new GridLayout(2,1));
    paneeli = paneeli(cal);
    add(paneeli);
    add(buttons(cal));
    setLocationRelativeTo(null);
    setVisible(true);
}
public JPanel paneeli(Calendar cal) {
    cal.set(Calendar.DATE, 1);
    cal.add(Calendar.DATE, -cal.get(Calendar.DAY_OF_WEEK)+2);

    JPanel paneeli = new JPanel();
    paneeli.setLayout(new GridLayout(6,7));
    for(int i = 0;i<6;++i) {
        for(int j = 0;j<7;++j) {
            JPanel label = new JPanel();
            label.setBackground(Color.RED);
            if (i == 0) {
                if (j == 0) {
                    // Top left corner, draw all sides
                    label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
                } else {
                    // Top edge, draw all sides except left edge
                    label.setBorder(BorderFactory.createMatteBorder(1,
                                                                0,
                                                                1,
                                                                1,
                                                                Color.BLACK));
                }
            } else {
                if (j == 0) {
                    // Left-hand edge, draw all sides except top
                    label.setBorder(BorderFactory.createMatteBorder(0,
                                                                1,
                                                                1,
                                                                1,
                                                                Color.BLACK));
                } else {
                    // Neither top edge nor left edge, skip both top and left lines
                    label.setBorder(BorderFactory.createMatteBorder(0,
                                                                0,
                                                                1,
                                                                1,
                                                                Color.BLACK));
                }
            }
            label.addMouseListener(new MouseAdapter() {
                 @Override
                 public void mousePressed(MouseEvent e) {
                    JPanel panel = (JPanel) e.getSource();
                    if (Color.RED.equals(panel.getBackground())) {
                        panel.setBackground(Color.PINK);
                        panel.revalidate();
                        panel.repaint();
                    }else{
                        panel.setBackground(Color.RED);
                        panel.revalidate();
                        panel.repaint();
                    }
                 }
            });
            JLabel labeli = new JLabel();
            labeli.setText(day.format(cal.getTime()));
            label.add(labeli);
            cal.add(Calendar.DATE, +1);
            paneeli.add(label);
        }
    }
    return paneeli;
}
public JPanel buttons(Calendar cal) {
    final Calendar calender = (Calendar) cal.clone();
    JPanel buttonPanel = new JPanel();
    JButton button = new JButton();
    JButton buttoni = new JButton();
    button.setText("Prev");
    buttonPanel.add(button);
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                calender.set(calender.YEAR,calender.MONTH-1,1);
                calender.add(Calendar.DATE, -calender.get(Calendar.DAY_OF_WEEK));
                Component[] comps = JavaCalendar.paneeli.getComponents();
                for (Component comp : comps) {
                    JPanel p = (JPanel) comp;
                    JLabel c = (JLabel) p.getComponent(0);
                    c.setText(day.format(calender.getTime()));
                    calender.add(Calendar.DATE, +1);
                }

        }
    });

    buttoni.setText("Next");
    buttonPanel.add(buttoni);
    buttoni.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                calender.set(calender.YEAR,calender.MONTH+1,1);
                calender.add(Calendar.DATE, -calender.get(Calendar.DAY_OF_WEEK));
                Component[] comps = JavaCalendar.paneeli.getComponents();
                for (Component comp : comps) {
                    JPanel p = (JPanel) comp;
                    JLabel c = (JLabel) p.getComponent(0);
                    c.setText(day.format(calender.getTime()));
                    calender.add(Calendar.DATE, +1);
                }   
        }
    });
    cal = (Calendar) calender.clone();
    return buttonPanel;
}
public static void main(String[] args) {
    new JavaCalendar();
}


}
4

1 回答 1

2

那里没有实施

  • 语言环境,

  • 特殊日子/Hollydays

  • 多选

  • range_selection

仅关于如何在更改时刷新网格(月份,年份)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;

/** 
 * Custom dialog box to enter dates. The <code>CalendarDateChooser</code>
 * class presents a calendar and allows the user to visually select a 
 * day, month and year so that it is impossible to enter an invalid 
 * date. 
 **/
public class CalendarDateChooser extends JDialog implements ItemListener, MouseListener, FocusListener, KeyListener, ActionListener {

    private static final long serialVersionUID = 1L;
    private static final String[] MONTHS = new String[]{"January", "February", "March",
        "April", "May", "June", "July", "August", "September", "October", "November", "December"}; // Names of the months.
    private static final String[] DAYS = new String[]{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};// Names of the days of the week.
    private static final Color WEEK_DAYS_FOREGROUND = Color.black;// Text color of the days of the weeks, used as column headers in  the calendar. 
    private static final Color DAYS_FOREGROUND = Color.blue;// Text color of the days' numbers in the calendar. 
    private static final Color SELECTED_DAY_FOREGROUND = Color.white;// Background color of the selected day in the calendar. 
    private static final Color SELECTED_DAY_BACKGROUND = Color.blue;// Text color of the selected day in the calendar. 
    private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(1, 1, 1, 1);// Empty border, used when the calendar does not have the focus. 
    private static final Border FOCUSED_BORDER = BorderFactory.createLineBorder(Color.yellow, 1);// Border used to highlight the selected day when the calendar  has the focus. 
    private static final int FIRST_YEAR = 2010;// First year that can be selected.
    private static final int LAST_YEAR = 2100;// Last year that can be selected.
    private GregorianCalendar calendar;// Auxiliary variable to compute dates. 
    /** Calendar, as a matrix of labels. The first row represents the  first week of the month, the second row, the second week, and 
    so on. Each column represents a day of the week, the first is  Sunday, and the last is Saturday. The label's text is the number 
    of the corresponding day. */
    private JLabel[][] days;
    /** Day selection control. It is just a panel that can receive the focus. The actual user interaction is driven by the  
    <code>CalendarDateChooser</code> class. */
    private FocusablePanel daysGrid;
    private JComboBox month;// Month selection control. */
    private JComboBox year;// Year selection control. */
    private JButton ok; // "Ok" button. */
    private JButton cancel;// "Cancel" button. */
    /** Day of the week (0=Sunday) corresponding to the first day of 
    the selected month. Used to calculate the position, in the 
    calendar ({@link #days}), corresponding to a given day. */
    private int offset;
    private int lastDay; // Last day of the selected month.
    private JLabel day;// Selected day.
    /** <code>true</code> if the "Ok" button was clicked to close the dialog box, <code>false</code> otherwise. */
    private boolean okClicked;

    /** 
     * Constructs a new <code>CalendarDateChooser</code> with the given title.
     * @param owner owner dialog 
     * @param title dialog title 
     **/
    public CalendarDateChooser(JDialog owner, String title) {
        super(owner, title, true);
        construct();
    }

    /** 
     * Constructs a new <code>CalendarDateChooser</code>.
     * @param owner owner dialog 
     **/
    public CalendarDateChooser(JDialog owner) {
        super(owner, true);
        construct();
    }

    /** 
     * Constructs a new <code>CalendarDateChooser</code> with the given title.
     * @param owner owner frame 
     * @param title dialog title 
     **/
    public CalendarDateChooser(JFrame owner, String title) {
        super(owner, title, true);
        construct();
    }

    /** 
     * Constructs a new <code>CalendarDateChooser</code>.
     * @param owner owner frame 
     **/
    public CalendarDateChooser(JFrame owner) {
        super(owner, true);
        construct();
    }

    /** 
     * Custom panel that can receive the focus. Used to implement the calendar control. 
     **/
    private static class FocusablePanel extends JPanel {

        private static final long serialVersionUID = 1L;

        /**
         * Constructs a new <code>FocusablePanel</code> with the given 
         * layout manager. 
         * 
         * @param layout layout manager 
         **/
        FocusablePanel(LayoutManager layout) {
            super(layout);
        }

        /**
         * Always returns <code>true</code>, since <code>FocusablePanel</code> can receive the focus. @return <code>true</code> 
         **/
        @Override
        public boolean isFocusable() {
            return true;
        }
    }

    /** 
     * Initializes this <code>CalendarDateChooser</code> object. Creates the controls, registers listeners and initializes the dialog box.
     **/
    private void construct() {
        Border line, raisedbevel, loweredbevel, title, empty;
        line = BorderFactory.createLineBorder(Color.black);
        raisedbevel = BorderFactory.createRaisedBevelBorder();
        loweredbevel = BorderFactory.createLoweredBevelBorder();
        title = BorderFactory.createTitledBorder("");
        empty = BorderFactory.createEmptyBorder(4, 4, 4, 4);
        Border compound;
        Border compound1;
        compound = BorderFactory.createCompoundBorder(empty, new RoundedBorderLine());
        Color crl = (Color.blue);
        compound1 = BorderFactory.createCompoundBorder(empty, new RoundedBorderLineBlue(crl));
        calendar = new GregorianCalendar();
        month = new JComboBox(MONTHS);//adds the monthes into the combobox 
        month.addItemListener(this);
        year = new JComboBox();//adds the years into the combobox 
        for (int i = FIRST_YEAR; i <= LAST_YEAR; i++) {
            year.addItem(Integer.toString(i));
        }
        year.addItemListener(this);
        days = new JLabel[7][7];
        for (int i = 0; i < 7; i++) {//set up the days in week display using DAYS constant 
            days[0][i] = new JLabel(DAYS[i], JLabel.RIGHT);
            days[0][i].setForeground(WEEK_DAYS_FOREGROUND);
        }
        for (int i = 1; i < 7; i++) {//set up the days 
            for (int j = 0; j < 7; j++) {
                days[i][j] = new JLabel(" ", JLabel.RIGHT);
                days[i][j].setForeground(DAYS_FOREGROUND);
                days[i][j].setBackground(SELECTED_DAY_BACKGROUND);
                days[i][j].setBorder(EMPTY_BORDER);
                days[i][j].addMouseListener(this);
            }
        }
        ok = new JButton("Ok");
        ok.addActionListener(this);
        ok.setFocusPainted(false);
        cancel = new JButton("Cancel");
        cancel.addActionListener(this);
        cancel.setFocusPainted(false);
        JPanel monthYear = new JPanel();
        monthYear.add(month);
        monthYear.add(year);
        daysGrid = new FocusablePanel(new GridLayout(7, 7, 5, 0));
        daysGrid.addFocusListener(this);
        daysGrid.addKeyListener(this);
        for (int i = 0; i < 7; i++) {
            for (int j = 0; j < 7; j++) {
                daysGrid.add(days[i][j]);
            }
        }
        daysGrid.setBackground(Color.white);
        daysGrid.setBorder(BorderFactory.createLoweredBevelBorder());
        JPanel daysPanel = new JPanel();
        daysPanel.add(daysGrid);
        JPanel buttons = new JPanel();
        buttons.add(ok);
        //buttons.add(cancel);
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());
        /*Container dialog = getContentPane();
        dialog.add("North", monthYear);
        dialog.add("Center", daysPanel);
        dialog.add("South", buttons);*/
        topPanel.add(monthYear, BorderLayout.NORTH);
        topPanel.add(daysPanel, BorderLayout.CENTER);
        topPanel.add(buttons, BorderLayout.SOUTH);
        topPanel.setBorder(compound1);
        add("Center", topPanel);
        setAlwaysOnTop(true);
        setUndecorated(true);
        pack();
        setResizable(false);
    }

    /** 
     * Gets the selected day, as an <code>int</code>. Parses the text  of the selected label in the calendar to get the day. 
     * @return the selected day or -1 if there is no day selected 
     **/
    private int getSelectedDay() {
        if (day == null) {
            return -1;
        }
        try {
            return Integer.parseInt(day.getText());
        } catch (NumberFormatException e) {
        }
        return -1;
    }

    /** 
     * Sets the selected day. The day is specified as the label control, in the calendar, corresponding to the day to select. 
     * @param newDay day to select 
     **/
    private void setSelected(JLabel newDay) {
        if (day != null) {
            day.setForeground(DAYS_FOREGROUND);
            day.setOpaque(false);
            day.setBorder(EMPTY_BORDER);
        }
        day = newDay;
        day.setForeground(SELECTED_DAY_FOREGROUND);
        day.setOpaque(true);
        if (daysGrid.hasFocus()) {
            day.setBorder(FOCUSED_BORDER);
        }
    }

    /**  Sets the selected day. The day is specified as the number of the day, in the month, to selected. The function compute the 
     * corresponding control to select. @param newDay day to select **/
    private void setSelected(int newDay) {
        setSelected(days[(newDay + offset - 1) / 7 + 1][(newDay + offset - 1) % 7]);
    }

    /** 
     * Updates the calendar. This function updates the calendar panel 
     * to reflect the month and year selected. It keeps the same day 
     * of the month that was selected, except if it is beyond the last 
     * day of the month. In this case, the last day of the month is 
     * selected. 
     **/
    private void update() {
        int iday = getSelectedDay();
        for (int i = 0; i < 7; i++) {
            days[1][i].setText(" ");
            days[5][i].setText(" ");
            days[6][i].setText(" ");
        }
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.MONTH, month.getSelectedIndex() + Calendar.JANUARY);
        calendar.set(Calendar.YEAR, year.getSelectedIndex() + FIRST_YEAR);
        offset = calendar.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
        lastDay = calendar.getActualMaximum(Calendar.DATE);
        for (int i = 0; i < lastDay; i++) {
            days[(i + offset) / 7 + 1][(i + offset) % 7].setText(String.valueOf(i + 1));
        }
        if (iday != -1) {
            if (iday > lastDay) {
                iday = lastDay;
            }
            setSelected(iday);
        }
    }

    /** 
     * Called when the "Ok" button is pressed. Just sets a flag and hides the dialog box. 
     * @param e 
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == ok) {
            okClicked = true;
        }
        setVisible(false);
    }

    /** 
     * Called when the calendar gains the focus. Just re-sets the 
     * selected day so that it is redrawn with the border that 
     * indicate focus. 
     *
     * @param e 
     */
    @Override
    public void focusGained(FocusEvent e) {
        setSelected(day);
    }

    /** 
     * Called when the calendar loses the focus. Just re-sets the 
     * selected day so that it is redrawn without the border that 
     * indicate focus. 
     *
     * @param e 
     */
    @Override
    public void focusLost(FocusEvent e) {
        setSelected(day);
    }

    /** 
     * Called when a new month or year is selected. Updates the calendar 
     * to reflect the selection. 
     *
     * @param e 
     */
    @Override
    public void itemStateChanged(ItemEvent e) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                update();
            }
        });
    }

    /** 
     * Called when a key is pressed and the calendar has the 
     * focus. Handles the arrow keys so that the user can select a day 
     * using the keyboard. 
     *
     * @param e 
     */
    @Override
    public void keyPressed(KeyEvent e) {
        int iday = getSelectedDay();
        switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
                if (iday > 1) {
                    setSelected(iday - 1);
                }
                break;
            case KeyEvent.VK_RIGHT:
                if (iday < lastDay) {
                    setSelected(iday + 1);
                }
                break;
            case KeyEvent.VK_UP:
                if (iday > 7) {
                    setSelected(iday - 7);
                }
                break;
            case KeyEvent.VK_DOWN:
                if (iday <= lastDay - 7) {
                    setSelected(iday + 7);
                }
                break;
        }
    }

    /** 
     * Called when the mouse is clicked on a day in the 
     * calendar. Selects the clicked day. 
     *
     * @param e 
     */
    @Override
    public void mouseClicked(MouseEvent e) {
        JLabel day1 = (JLabel) e.getSource();
        if (!day1.getText().equals(" ")) {
            setSelected(day1);
        }
        daysGrid.requestFocus();
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    /** 
     * Selects a date. Displays the dialog box, with a given date as 
     * the selected date, and allows the user select a new date. 
     * @param date initial date 
     * @return the new date selected or <code>null</code> if the user 
     * press "Cancel" or closes the dialog box 
     **/
    public Date select(Date date) {
        calendar.setTime(date);
        int _day = calendar.get(Calendar.DATE);
        int _month = calendar.get(Calendar.MONTH);
        int _year = calendar.get(Calendar.YEAR);
        year.setSelectedIndex(_year - FIRST_YEAR);
        month.setSelectedIndex(_month - Calendar.JANUARY);
        setSelected(_day);
        okClicked = false;
        setVisible(true);
        if (!okClicked) {
            return null;
        }
        calendar.set(Calendar.DATE, getSelectedDay());
        calendar.set(Calendar.MONTH, month.getSelectedIndex() + Calendar.JANUARY);
        calendar.set(Calendar.YEAR, year.getSelectedIndex() + FIRST_YEAR);
        return calendar.getTime();
    }

    public void setDate(Date date) {
        calendar.setTime(date);
        int _day = calendar.get(Calendar.DATE);
        int _month = calendar.get(Calendar.MONTH);
        int _year = calendar.get(Calendar.YEAR);
        year.setSelectedIndex(_year - FIRST_YEAR);
        month.setSelectedIndex(_month - Calendar.JANUARY);
        setSelected(_day);
    }

    public Date getDate() {
        calendar.set(Calendar.DATE, getSelectedDay());
        calendar.set(Calendar.MONTH, month.getSelectedIndex() + Calendar.JANUARY);
        calendar.set(Calendar.YEAR, year.getSelectedIndex() + FIRST_YEAR);
        return calendar.getTime();
    }

    /** 
     * Selects new date. Just calls {@link #select(Date)} with the 
     * system date as the parameter. 
     * 
     * @return the same as the function {@link #select(Date)} 
     **/
    public Date select() {
        return select(new Date());
    }
}
于 2013-05-29T08:41:21.370 回答