The below code works as intended and I'm generally happy with it - the sliders each change an RGB value to modify the color of the circle in circlePanel. Likewise the diameter slider changes the size.
Could the code be refactored/restructured to make it better/more readable? The CircleSlider constructor is quite long - I'm wondering could some of it be removed to separate methods/classes.
CircleSlider.java
//import statements
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
//CircleSlider class to setup GUI and main logic
public class CircleSlider extends JFrame{
//instantiate GUI components
private final JPanel circlePanel;
private final JSlider diameterSlider, redSlider, greenSlider, blueSlider;
private final JLabel diameterLabel, redLabel, greenLabel, blueLabel;
private final JTextArea displayArea;
private final GridBagLayout layout;
private final GridBagConstraints constraints;
//circle properties
private int diameter = 75;
private Color circleColor;
//constructor to set up GUI
public CircleSlider(){
//call to JFrame constructor to set title
super("Circle Slider");
//create new layout
layout = new GridBagLayout();
constraints = new GridBagConstraints();
setLayout(layout);
//add calculation display area
displayArea = new JTextArea(6,10);
displayArea.setText("Adjust the diameter slider to see information on the circle");
addComponent(displayArea, 14, 0, 20, 8, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER);
//add JPanel to house the circle
circlePanel = new JPanel(){
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
//set color of drawn graphics
g.setColor(circleColor);
//Draw circle in centre of circlePanel
g.fillOval((circlePanel.getWidth() - diameter) / 2, (circlePanel.getHeight() - diameter) / 2,
diameter, diameter);
}
};
addComponent(circlePanel, 1, 3, 16, 11, 1, 1,
GridBagConstraints.BOTH, GridBagConstraints.CENTER);
//add label for diameter slider
diameterLabel = new JLabel("Diameter");
addComponent(diameterLabel, 1, 1, 1, 1, 0, 1,
GridBagConstraints.NONE, GridBagConstraints.WEST);
//add the slider to control diameter of circle
diameterSlider = new JSlider(0, 150, 50);
//add listener as anonymous inner class
diameterSlider.addChangeListener(
new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
double radius = diameter / 2.0;
setDiameter(diameterSlider.getValue());
String message = String.format(
"Diameter: %d%nArea: %.2f%nCircumference: %.2f",
diameter, getArea(radius), getCircumference(radius));
displayArea.setText(message);
}
}
);
addComponent(diameterSlider, 2, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
//create listener for color sliders
SliderListener sliderListener = new SliderListener();
//add redSlider and label
redLabel = new JLabel("RGB: Red");
addComponent(redLabel, 4, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
redSlider = new JSlider(0, 255, 0);
redSlider.addChangeListener(sliderListener);
addComponent(redSlider, 5, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
//add greenSlider and label
greenLabel = new JLabel("RGB: Green");
addComponent(greenLabel, 7, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
greenSlider = new JSlider(0, 255, 0);
greenSlider.addChangeListener(sliderListener);
addComponent(greenSlider, 8, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
//add blueSlider and label
blueLabel = new JLabel("RGB: Blue");
addComponent(blueLabel, 11, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
blueSlider = new JSlider(0, 255, 0);
blueSlider.addChangeListener(sliderListener);
addComponent(blueSlider, 12, 1, 1, 1, 0, 1, GridBagConstraints.NONE,
GridBagConstraints.WEST);
}
//ChangeListener for color sliders - implemented as private inner class as
//all color sliders perform same method, setColor()
class SliderListener implements ChangeListener{
@Override
public void stateChanged(ChangeEvent e){
setColor(redSlider.getValue(), greenSlider.getValue(), blueSlider.getValue());
}
}
//helper method to add a component to JPanel or JFrame
private void addComponent(Component component, int row, int column, int width, int height,
int weightx, int weighty, int fillConstraint, int anchorConstraint) {
constraints.gridx = column;
constraints.gridy = row;
constraints.gridwidth = width;
constraints.gridheight = height;
constraints.weightx = weightx;
constraints.weighty = weighty;
constraints.fill = fillConstraint;
constraints.anchor = anchorConstraint;
layout.setConstraints(component, constraints);
add(component);
}
//set the diameter of the circle
private void setDiameter(int newDiameter){
//if new diameter is negative, set to 10
diameter = newDiameter >= 0 ? newDiameter : 10;
repaint();
}
//set the color of the circle
private void setColor(int newRed, int newGreen, int newBlue){
circleColor = new Color(
//if any given color is negative, set to 10
newRed >= 0 ? newRed : 10,
newGreen >= 0 ? newGreen : 10,
newBlue >= 0 ? newBlue : 10);
getGraphics().setColor(circleColor);
repaint();
}
//Find the area of a circle given the radius
private double getArea(double radius){
return Math.PI * Math.pow((radius), 2);
}
//find circumference of circle given the radius
private double getCircumference(double radius){
return 2 * Math.PI * radius;
}
}
CircleSliderTest.java
import javax.swing.*;
public class CircleSliderTest {
public static void main(String[] args){
CircleSlider app = new CircleSlider();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(600,400);
app.setVisible(true);
}
}