patternjavaMinor
Using swing and creating JPanel
Viewed 0 times
creatingjpanelswingusingand
Problem
I watched bunch of videos about swing and GUI in general and created my first component (correct me if it is not one).
```
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 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
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 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
Solution
I think you are being too harsh on yourself. Your code is not particularly messy. It's quite difficult to build up a Swing component without code starting to feel a little untidy. I occasionally split such code into builder methods (e.g.
To answer your stream question, if you use
However, since
Other observations:
-
Your
-
Most of your classes are missing a
-
(Very minor, more of an FYI...) Methods declared in interfaces are always
-
Your
-
Closing your frame doesn't currently end your program. You may want to add
private JPanel buildSomeComplicatedPanel()), but I think your code is fine in that regard.To answer your stream question, if you use
boxed() you can convert a primitive int stream into an Integer stream:IntStream.range(0, 10).boxed().map(i -> i + year).toArray(size -> new Integer[size]);However, since
IntStream::range takes start and end parameters, you can simply this to:IntStream.range(year, year + 10).boxed().toArray(size -> new Integer[size]);Other observations:
-
Your
JComboBox objects should use generic types. I.e. JComboBox yearComboBox and JComboBox monthComboBox.-
Most of your classes are missing a
serialVersionUID value. Your IDE ought to prompt you about this. (Eclipse certainly does).-
(Very minor, more of an FYI...) Methods declared in interfaces are always
public, so you don't need to include that keyword in each method signature.-
Your
CinemaFrame class extends JFrame. However, most Swing gurus would encourage you to use composition rather than inheritance:public class CinemaFrame {
private final JFrame frame;
public CinemaFrame(String title) {
frame = new JFrame(title);
frame.setLayout(new GridBagLayout());
CalendarPanel calendarPanel = new CalendarPanel();
calendarPanel.addCalendarListener(e -> System.out.println(e.getSource()));
frame.add(calendarPanel);
frame.pack(); // You may wish to do this in the constructor
}
public void showFrame() {
frame.setVisible(true);
}
// Example main method I used for testing...
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> new CinemaFrame("Foo").showFrame());
}
}-
Closing your frame doesn't currently end your program. You may want to add
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); into your CinemaFrame class.Code Snippets
IntStream.range(0, 10).boxed().map(i -> i + year).toArray(size -> new Integer[size]);IntStream.range(year, year + 10).boxed().toArray(size -> new Integer[size]);public class CinemaFrame {
private final JFrame frame;
public CinemaFrame(String title) {
frame = new JFrame(title);
frame.setLayout(new GridBagLayout());
CalendarPanel calendarPanel = new CalendarPanel();
calendarPanel.addCalendarListener(e -> System.out.println(e.getSource()));
frame.add(calendarPanel);
frame.pack(); // You may wish to do this in the constructor
}
public void showFrame() {
frame.setVisible(true);
}
// Example main method I used for testing...
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> new CinemaFrame("Foo").showFrame());
}
}Context
StackExchange Code Review Q#85753, answer score: 3
Revisions (0)
No revisions yet.