1

I have a problem and it has been bugging me a long time now...

I have a JPanel with gridlayout(6,7) and my problem is updating the data correctly. I'm making a simple calendar software and of course I'm using Calendar. The problem is when I change Calendar object MONTH field and getting new month data to this JPanel gridlayout but the data isn't correctly showed.

Am I calculating my data fields incorreclty or how should I update the MONTH field. I have tryed 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);
                }

        }
    });

Is it because for loop goes around 42 times and it updates every field and calls add() everytime...? The data updates little bit incorrect... Example May 1st is Wensday and June 1st is Saturday, but when this actionPerfomed() is called it shows June 1st is Sunday.

SSCE code

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


}
Leolian
  • 181
  • 1
  • 1
  • 8

1 Answers1

2

isn't there implemented

  • Locale,

  • Special days/Hollydays

  • multi_selection

  • range_selection

only about how to refresh grid on change (moth, year)

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());
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Cant find class RoundedBordedLine @Edit There is implemented locale, but other things aren't important to this software what I'm doing... – Leolian May 29 '13 at 09:19
  • please you can to ignore that, [here is one of attempts](http://stackoverflow.com/a/5755124/714968) – mKorbel May 29 '13 at 09:47