I'm making a Calendar in java for my Programming II class and I need some help. I've made my calendar so that it is 6 x 7 grid of buttons and created a method which changes the button text to match the selected month (chosen by a radio button). It works for the default selected month, but I can't get it to update the ui when a new radio button is selected. My formatCalendar method as well as my calendar buttons are in a class CalendarPanel which extends JPanel, but my radio buttons are in MonthRadioButtonPanel which also extends JPanel. I know my action listeners on the radio buttons work because I've tested it with a simple System.out.println... Thank you, any help is greatly appreciated!

My radio buttons are created in the MonthRadioButtonPanel() constructor.

JRadioButton[] monthRadioButton;
RadioButtonListener listener = new RadioButtonListener();

public MonthRadioButtonPanel()
{
    monthRadioButton = new JRadioButton[12];
    ButtonGroup monthSelect = new ButtonGroup();

    this.setLayout(new GridLayout(2,6));

    //creates radio buttons with labels and default selected value
    monthRadioButton[0] = new JRadioButton("January",true);
    monthRadioButton[1] = new JRadioButton("February",false);
    monthRadioButton[2] = new JRadioButton("March",false);
    monthRadioButton[3] = new JRadioButton("April",false);
    monthRadioButton[4] = new JRadioButton("May",false);
    monthRadioButton[5] = new JRadioButton("June",false);
    monthRadioButton[6] = new JRadioButton("July",false);
    monthRadioButton[7] = new JRadioButton("August",false);
    monthRadioButton[8] = new JRadioButton("September",false);
    monthRadioButton[9] = new JRadioButton("October",false);
    monthRadioButton[10] = new JRadioButton("November",false);
    monthRadioButton[11] = new JRadioButton("December",false);

    for (int i = 0; i < monthRadioButton.length; i++)
    {
        //adds radio buttons and an action listener to each 
        monthSelect.add(monthRadioButton[i]);
        monthRadioButton[i].addActionListener(listener);      
        monthRadioButton[i].setActionCommand(monthRadioButton[i].getText());
        this.add(monthRadioButton[i]);                        
    }

}

I am using an inner class to listen to the radio buttons. The method formatCalendar(int nDays, int firstDayOfWeek) is in the CalendarPanel class and it formats the calendar correctly given the number of days in the month and the first day of the week for the 1st of the month (e.g. Mon, Tues using the int representation). The methods getDaysInMonth() and getFirstDayOfWeek() are in MonthRadioButtonPanel and find the days in the month and the first day of week in the month for whichever radio button is selected. This works fine for the default selection (in this case January) but the UI does not refresh when new radio buttons are selected. This is my inner RadioButtonListener class.

class RadioButtonListener implements ActionListener
{
    //listens to radio buttons and reformats calendar
    public void actionPerformed(ActionEvent e)
    {
        //this is just a test to see if the listeners are working correctly; it works
        System.out.println(e.getActionCommand()); 

        //actual code trying to reformat CalendarPanel when a radio button is clicked
        CalendarPanel cal = new CalendarPanel();
        cal.formatCalendar(getDaysInMonth(), getFirstDayOfWeek());
        cal.revalidate();
        cal.repaint();

    }

}

Edit

So I changed my RadioButtonListener exactly as @Hovercraft Full Of Eels suggested so it looks like:

class RadioButtonListener implements ActionListener
{
    private CalendarPanel cal;

    public RadioButtonListener()
    {

    }

    public RadioButtonListener(CalendarPanel cal) {
        this.cal = cal;
    }

    public void actionPerformed(ActionEvent e)
    {
        cal.formatCalendar(getDaysInMonth(), getFirstDayOfWeek());
        cal.revalidate();
        cal.repaint();
    }    
}

}

And my Frame class constructor compiles fine, but when I click a radio button it throws a null pointer exception.

public class Frame extends JFrame
{

//creates frame with added panels
public Frame()
{
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("Calendar");
    this.setSize(900,400);
    this.setLayout(new BorderLayout());

    MonthRadioButtonPanel mon = new MonthRadioButtonPanel();
    this.add(mon, BorderLayout.SOUTH);

    CalendarPanel cal = new CalendarPanel();

    MonthRadioButtonPanel.RadioButtonListener list = mon.new RadioButtonListener(cal);

    this.add(cal, BorderLayout.WEST);
    this.add(new TitlePanel(), BorderLayout.NORTH);

    this.setVisible(true);

}

}
有帮助吗?

解决方案

You're making changes to the wrong CalendarPanel object, to one created specifically in the listener. Meanwhile the CalendarPanel object that is displayed knows nothing of these changes.

class RadioButtonListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        // the line below creates a *new* CalendarPanel object
        // one completely unrelated to the displayed CalendarPanel 
        CalendarPanel cal = new CalendarPanel();
        cal.formatCalendar(getDaysInMonth(), getFirstDayOfWeek());
        cal.revalidate();
        cal.repaint();
    }    
}

___________________________

The solution is to pass a reference to the displayed CalendarPanel object to your listener, and make changes on that.

class RadioButtonListener implements ActionListener
{
    private CalendarPanel cal;

    public RadioButtonListener(CalendarPanel cal) {
       this.cal = cal;
    }
    public void actionPerformed(ActionEvent e)
    {
        cal.formatCalendar(getDaysInMonth(), getFirstDayOfWeek());
        cal.revalidate();
        cal.repaint();
    }    
}

When creating this above listener, you'll need to pass a reference to the valid displayed CalendarPanel object to allow it to work.


Edit
You state in comment:

Okay, I did that and instantiated it in my Frame constructor (which also creates and adds my other panels) but it creates a null pointer exception.

If you have any significant changes to your question, please edit your question (as I'm doing now), by posting new code and new description to the bottom of your current question. Don't change the original question or code if you can avoid doing so as not to invalidate your answers.

Now on to your problem: I can only guess since we are not seeing your changed code, but are you passing in the CalendarPlayer variable into the RadioButtonListener constructor before you've assigned a valid CalendarPlayer to its variable. If so, that would explain this since you would be passing null into the RadioButtonListener constructor. The solution would be to assign a CalendarPlayer to its variable first before calling the RadioButtonListener constructor.


Edit 2

You're likely creating two RadioButtonListener's, one using the default constructor, the one without the parameter, and one that uses the parameter. Get rid of that default constructor, again the one without the parameter, don't create two of these objects (it makes no sense and makes me scratch my head why you'd do this) and work on figuring out a way to get the proper reference into the listener. You should be able to figure this out if you think on it, and don't just copy and paste code from here.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top