Skip to main content
1 of 3
Townsheriff
  • 491
  • 4
  • 19

Using swing and creating JPanel

I watched bunch of videos about swing and GUI in general and created my first component(correct me if it is not one).

Here is the code:

JPanel class:

package gui.pane;

import javax.swing.*;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;


public class CalendarPanel extends JPanel {
    private List<JButton> dateButtons = new ArrayList<>();
    private Calendar selectedDate;
    private final JPanel datePanel;
    private EventListenerList listenerList = new EventListenerList();

    public CalendarPanel() {
        this(Calendar.getInstance());
    }

    public CalendarPanel(Calendar selectedDate) {
        this.selectedDate = selectedDate;
        setBorder(BorderFactory.createTitledBorder("Calendar"));

        // year combo box
        final JComboBox yearComboBox = new JComboBox<>(getYearList(selectedDate.get(Calendar.YEAR)));
        yearComboBox.addActionListener( e -> {
                selectedDate.set(Calendar.YEAR, (Integer) yearComboBox.getSelectedItem());
                updateDateButtons();
            }
        );

        //month combo box
        final JComboBox monthComboBox = new JComboBox<>(new DateFormatSymbols().getMonths());
        monthComboBox.setSelectedIndex(selectedDate.get(Calendar.MONTH));
        monthComboBox.addActionListener( e -> {
                selectedDate.set(Calendar.MONTH, monthComboBox.getSelectedIndex());
                updateDateButtons();
             }
        );

        // creating panels
        final JPanel calendarPanel = new JPanel();
        calendarPanel.setLayout(new BorderLayout());

        // create month and year panel
        final JPanel MonthAndYearPanel = new JPanel();
        MonthAndYearPanel.setLayout(new FlowLayout());

        // add year and month combo boxes to sub panel
        MonthAndYearPanel.add(yearComboBox);
        MonthAndYearPanel.add(monthComboBox);

        // creates date panel
        datePanel = new JPanel();
        datePanel.setLayout(new GridBagLayout());
        createDateButtons();

        // add sub panels to main panel
        calendarPanel.add(MonthAndYearPanel, BorderLayout.PAGE_START);
        calendarPanel.add(datePanel, BorderLayout.PAGE_END);

        add(calendarPanel);

    }

    private Integer[] getYearList(int year) {
        Integer[] arr = new Integer[10];
        for(int index = 0; index < 10; index++) {
            arr[index] = year + index;
        }
        return arr;
    }

    private void updateDateButtons(){
        deleteDateButtons();
        createDateButtons();
    }

    private void deleteDateButtons() {
        dateButtons.stream().forEach(datePanel::remove);
        dateButtons = new ArrayList<>();
        datePanel.revalidate();
        datePanel.repaint();
    }

    private void createDateButtons() {
        // sets date to first date of month
        selectedDate.set(Calendar.DATE, 1);

        // initializes grid
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.PAGE_START;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.insets = new Insets(2,2,2,2);

        // placing buttons on the grid
        gbc.gridy = 0;
        gbc.gridx = selectedDate.get(Calendar.DAY_OF_WEEK) - 1;
        for(int index = 0; index < selectedDate.getActualMaximum(Calendar.DAY_OF_MONTH); index++) {
            JButton button = new JButton(String.valueOf(index + 1));

            // adds actions listener to button
            button.addActionListener( e -> {
                selectedDate.set(Calendar.DATE, dateButtons.indexOf((JButton) e.getSource()) + 1);
                CalendarEvent calendarEvent = new CalendarEvent(e,selectedDate);
                fireCalendarEvent(calendarEvent);
            });

            datePanel.add(button, gbc);
            dateButtons.add(button);
            gbc.gridx++;
            if (gbc.gridx == 7) {
                gbc.gridy++;
                gbc.gridx = 0;
            }
        }

        // resetting panel and date
        datePanel.revalidate();
        datePanel.repaint();
    }

    public void fireCalendarEvent(CalendarEvent event) {
        Object[] listeners = listenerList.getListenerList();

        for(int index = 0; index < listeners.length; index += 2) {
            if (listeners[index] == CalendarListener.class) {
                ((CalendarListener) listeners[index + 1]).CalendarEventOccurred(event);
            }
        }
    }

    public void addCalendarListener(CalendarListener listener) {
        listenerList.add(CalendarListener.class, listener);

    }

    public void removeCalendarListener(CalendarListener listener) {
        listenerList.remove(CalendarListener.class, listener);
    }
}

CalendarEvent class:

package gui.pane;

import java.util.Calendar;
import java.util.EventObject;

public class CalendarEvent extends EventObject {

    private Calendar date;

    public CalendarEvent(Object source, Calendar date) {
        super(source);
        this.date = date;
    }

    public Calendar getDate() {
        return date;
    }

}

CalendarListener class:

package gui.pane;

import java.util.EventListener;

public interface CalendarListener extends EventListener {
    public void CalendarEventOccurred(CalendarEvent event);
}

and CinemaFrame class:

package gui;

import gui.pane.CalendarPanel;

import javax.swing.*;
import java.awt.*;

public class CinemaFrame extends JFrame {

    public CinemaFrame(String title) {
        super(title);
        setLayout(new GridBagLayout());
        CalendarPanel calendarPanel = new CalendarPanel();
        calendarPanel.addCalendarListener( e -> System.out.println(e.getSource()));
        add(calendarPanel);

    }
}

Basically this is little part of my homework.

I have some questions:

  1. I couldn't figure out a way to format this code so it wouldn't look messy, that why I added a lot of comments that doesn't really mean anything. I could make a bunch of functions, but then I would have to pass lot of arguments. That does not seem any less messy. How do you approach this?

  2. Also I try to use latest features: lambda expressions, streams. There was places I couldn't figure out how to use them in some situations.

For example here:

private Integer[] getYearList(int year) { Integer[] arr = new Integer[10]; for(int index = 0; index < 10; index++) { arr[index] = year + index; } return arr; }

I only could create int array: IntStream.range(0, 10).map(i -> year + i).toArray();

So tell me where I could use something better then I have.

  1. What else is on your mind to improving this code(patterns, naming, other built in classes, etc..)?

![Calendar image][1] [1]: https://i.sstatic.net/R1AMp.jpg

Townsheriff
  • 491
  • 4
  • 19