Search code examples
javaswingjpaneljbuttonrepaint

How to repaint a Panel from inside


So I have a Calendar GUI using a borderlayout. There is a header (north) with combo boxes of month and years. When I select an item in the month combo box say, June, then it will update the calendar and repaint the center (The center has 42 JButtons). The center is a JPanel filled with button. The buttons are intractable to display events of that day (Just listing as much information as I can).

My problem is repainting the panel and stretching the frame. When I stretch the frame, for some reason the Center Panel repeats itself. When I call revalidate, it continues to repeat itself.

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

public class cPan extends JPanel implements ChangeListener
{
String date;
public HashMap<String, ArrayList<Event>> haM;
DataModel data;
JButton dayB;
MyCalendar cal;

public cPan(MyCalendar c, HashMap<String, ArrayList<Event>> hm, DataModel d)
{
    haM = hm;
    data = d;
    cal = c;
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    int year = cal.get(Calendar.YEAR);
    int month = cal.get(Calendar.MONTH);
    System.out.println(month);
    int day = cal.get(Calendar.DAY_OF_MONTH);
    int daysInMonth = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
    Calendar calForDay = Calendar.getInstance();
    calForDay.set(Calendar.DATE, day);
    calForDay.set(Calendar.MONTH, month);
    calForDay.set(Calendar.YEAR, year);
    calForDay.set(Calendar.DAY_OF_MONTH, 1);
    Date firstDayOfMonth = calForDay.getTime();
    int counter = 0;
    SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
    String fDOM = sdf.format(firstDayOfMonth);

    //print empty buttons
    if(fDOM.equalsIgnoreCase("SUNDAY")) {counter = 1;}
    if(fDOM.equalsIgnoreCase("MONDAY")) {counter = 2;}
    if(fDOM.equalsIgnoreCase("TUESDAY")) {counter = 3;}
    if(fDOM.equalsIgnoreCase("WEDNESDAY")) {counter = 4;}
    if(fDOM.equalsIgnoreCase("THURSDAY")) {counter = 5;}
    if(fDOM.equalsIgnoreCase("FRIDAY")) {counter = 6;}
    if(fDOM.equalsIgnoreCase("SATURDAY")) {counter = 7;}
    setLayout(new GridLayout(7,7));
    DAYS[] arrOfDays = DAYS.values();
    for(DAYS s : arrOfDays)
    {
        dayB = new JButton(s.name());
        dayB.setBackground(new Color(255, 204, 153 , 255));
        add(dayB);
    }
    for (int j = 1; j < counter; j++)
    {
        dayB.setBackground(new Color(255, 229, 204, 255));
        dayB = new JButton("");
        add(dayB);
    }
    //print day buttons
    for(int i = 1; i <= daysInMonth; i++)
    {
        String dayNum = String.valueOf(i);
        String monthNum = String.valueOf(month + 1);
        String yearNum = String.valueOf(year);
        String dayNum2 = dayNum;
        if(dayNum.length() == 1)
        {
            dayNum2 = "0" + dayNum;
        }
        if(String.valueOf(month).length() == 1)
        {
            monthNum = "0" + monthNum;
        }
        date = yearNum + monthNum + dayNum2;

        dayB = new JButton(dayNum);
        if(i == day)
        {
            dayB.setBackground(new Color(153, 255, 153, 255));
        }
        else if(haM.containsKey(date))
        {
            dayB.setBackground(new Color(255, 255, 153, 255));
        }
        else
        {
            dayB.setBackground(new Color(255, 229, 204, 255));
        }
        dayB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DayFrame dayF = new DayFrame(date, haM);
            }
        });
        add(dayB);
        counter++;
    }
    //print empty buttons
    for(int i = counter; i <= 42; i++)
    {
        dayB = new JButton("");
        dayB.setBackground(new Color(255, 229, 204, 255));
        add(dayB);
    }
}

public void stateChanged(ChangeEvent e) {
    System.out.println("Something is going on in statechange");
    cal.set(Calendar.MONTH, 10); // only did this to test it out
    cPan.this.revalidate();
    cPan.this.repaint();
}
}

Solution

  • Your paintComponent method is doing many things that it should never do, such as create and place components. It should paint and paint only.

    I suggest that instead you place your components into your GUI inside of your class's constructor, and again use paintComponent just for painting and nothing else. If you're wanting to display a calendar, consider displaying each day as a JPanel held in a GridLayout-using JPanel. The DayPanel could be in its own class in order to refactor out the information.

    Also, you should rename your class, since by convention class names should begin with an upper case letter, and so something like CalendarPanel would be better.