I watched bunch of videos about swing and GUI in general and created my first component (correct me if it is not one).
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:
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?
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();
Tell me where I could use something better then I have.
What else is on your mind to improving this code(patterns, naming, other built in classes, etc..)?