import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/** An instance of this class shows a color and its complement as well
* as sliders for the RGB, HSV, and CMYK color models. Changing any
* of the sliders changes the color (and the other sliders appropriately).
*/
public class A4 extends JApplet implements ChangeListener, ActionListener {
/** the JFrame that is the GUI. */
private JFrame jf= null;
/** Panels that contain the color and its complement, and
labels that contain information in them. */
private JPanel image, compImage;
private JLabel imageLabel, compImageLabel;
/** Below are sliders. In each constructor call, the first argument
makes it a vertical slider. The next three arguments are the
minimum value, maximum value, and initial value of the slider. */
/** RGB sliders. */
private JSlider RSlider= new JSlider(JSlider.VERTICAL, 0, 25500, 0);
private JSlider GSlider= new JSlider(JSlider.VERTICAL, 0, 25500, 25500);
private JSlider BSlider= new JSlider(JSlider.VERTICAL, 0, 25500, 0);
/** CMYK sliders. */
private JSlider CSlider= new JSlider(JSlider.VERTICAL, 0, 10000, 10000);
private JSlider MSlider= new JSlider(JSlider.VERTICAL, 0, 10000, 0);
private JSlider YSlider= new JSlider(JSlider.VERTICAL, 0, 10000, 10000);
private JSlider KSlider= new JSlider(JSlider.VERTICAL, 0, 10000, 0);
/** HSV sliders. */
private JSlider HSlider= new JSlider(JSlider.VERTICAL, 0, 35999, 12000);
private JSlider SSlider= new JSlider(JSlider.VERTICAL, 0, 100, 100);
private JSlider VSlider= new JSlider(JSlider.VERTICAL, 0, 100, 100);
/** The fields for the components of the colors and
the input buttons */
private JButton inputrgb= new JButton("RGB");
private JTextField rfield= new JTextField();
private JTextField gfield= new JTextField();
private JTextField bfield= new JTextField();
private JButton inputcmyk= new JButton("CMYK");
private JTextField cfield= new JTextField();
private JTextField mfield= new JTextField();
private JTextField yfield= new JTextField();
private JTextField kfield= new JTextField();
private JButton inputhsv= new JButton("HSV");
private JTextField hfield= new JTextField();
private JTextField sfield= new JTextField();
private JTextField vfield= new JTextField();
/** Create and show a GUI that contains:
* (0) a color panel, with text to describe the color.
* (1) the complementary color panel, with text to describe it.
* (2) Sliders for RGB, HSV, and CMYK.
* Initially, the color is red.
*/
public static void main(String[] args) {
A4 a4 = new A4();
}
/** Initialize the applet by creating and showing the GUI. */
public void init() {
// A4 a4= new A4();
}
/** Constructor: a GUI that contains:
* (0) a color panel, with text to describe the color.
* (1) the complementary color panel, with text to describe it.
* (2) Sliders for RGB, HSV, and CMYK.
* Initially, the color is red.
*/
public A4() {
jf= new JFrame("Color");
jf.setSize(600, 200);
jf.setResizable(false);
// Create color red in three models.
Color rgb= new Color(0, 255, 0);
CMYK cmyk= A4Methods.convertRGBtoCMYK(rgb);
HSV hsv= A4Methods.convertRGBtoHSV(rgb);
// Create panel image to contain the color.
image= new JPanel();
image.setSize(230, 200);
image.setPreferredSize(new Dimension(230, 200));
imageLabel= new JLabel("");
imageLabel.setPreferredSize(new Dimension(230, 160));
imageLabel.setVerticalAlignment(JLabel.TOP);
image.add(imageLabel);
// Create panel compImage to contain the complementary color.
compImage= new JPanel();
compImage.setSize(230, 200);
compImage.setPreferredSize(new Dimension(230, 200));
compImageLabel= new JLabel("");
compImageLabel.setPreferredSize(new Dimension(230, 160));
compImageLabel.setVerticalAlignment(JLabel.TOP);
compImage.add(compImageLabel);
// Create each of the sliders and add them to Box sliders
// with some space between the three sets of sliders.
Box sliders= new Box(BoxLayout.X_AXIS);
fixSlider(sliders, RSlider, 'R');
fixSlider(sliders, GSlider, 'G');
fixSlider(sliders, BSlider, 'B');
sliders.add(Box.createRigidArea(new Dimension(20,0)));
fixSlider(sliders, CSlider, 'C');
fixSlider(sliders, MSlider, 'M');
fixSlider(sliders, YSlider, 'Y');
fixSlider(sliders, KSlider, 'K');
sliders.add(Box.createRigidArea(new Dimension(20,0)));
fixSlider(sliders, HSlider, 'H');
fixSlider(sliders, SSlider, 'S');
fixSlider(sliders, VSlider, 'V');
// Add to Box GUI the color and complementary color panels and
// the Box of sliders
Box GUI= new Box(BoxLayout.X_AXIS);
GUI.add(image);
GUI.add(compImage);
GUI.add(sliders);
// Set the initial values of the sliders.
setSliders(rgb, hsv, cmyk);
// Set the color and complementary color panels
setColorPanels(rgb, hsv, cmyk);
Box fields= createFields();
Box finalBox= new Box(BoxLayout.Y_AXIS);
finalBox.add(GUI);
finalBox.add(fields);
jf.getContentPane().add(finalBox);
jf.pack();
jf.setVisible(true);
}
/** Create and return a horizontal box with the fields for the color components
* and the input buttons, registering this class as a listener for the buttons
*/
public Box createFields() {
Box fields= new Box(BoxLayout.X_AXIS);
fields.add(inputrgb);
inputrgb.addActionListener(this);
fields.add(new JLabel("R"));
fields.add(rfield);
fields.add(new JLabel("G"));
fields.add(gfield);
fields.add(new JLabel("B"));
fields.add(bfield);
fields.add(inputcmyk);
inputcmyk.addActionListener(this);
fields.add(new JLabel("C"));
fields.add(cfield);
fields.add(new JLabel("M"));
fields.add(mfield);
fields.add(new JLabel("Y"));
fields.add(yfield);
fields.add(new JLabel("K"));
fields.add(kfield);
fields.add(inputhsv);
inputhsv.addActionListener(this);
fields.add(new JLabel("hue"));
fields.add(hfield);
fields.add(new JLabel("sat"));
fields.add(sfield);
fields.add(new JLabel("val"));
fields.add(vfield);
return fields;
}
/** Create a Box with slider s and c above it
* and add the Box to sliders.
* Add this object as a changeListener for s.
*/
public void fixSlider(Box sliders, JSlider s, char c) {
Box b= new Box(BoxLayout.Y_AXIS);
b.add(new JLabel("" + c));
b.add(s);
sliders.add(b);
s.addChangeListener(this);
}
/** Add change listeners for sliders if b;
* Remove changelisteners for sliders if !b.
*/
public void fixListeners(boolean b) {
if (b) {
RSlider.addChangeListener(this);
GSlider.addChangeListener(this);
BSlider.addChangeListener(this);
HSlider.addChangeListener(this);
SSlider.addChangeListener(this);
VSlider.addChangeListener(this);
CSlider.addChangeListener(this);
MSlider.addChangeListener(this);
YSlider.addChangeListener(this);
KSlider.addChangeListener(this);
} else {
RSlider.removeChangeListener(this);
GSlider.removeChangeListener(this);
BSlider.removeChangeListener(this);
CSlider.removeChangeListener(this);
MSlider.removeChangeListener(this);
YSlider.removeChangeListener(this);
KSlider.removeChangeListener(this);
HSlider.removeChangeListener(this);
SSlider.removeChangeListener(this);
VSlider.removeChangeListener(this);
}
}
/** Process a movement in one of the sliders */
public void stateChanged(ChangeEvent e) {
Color rgb;
CMYK cmyk;
HSV hsv;
// Remove listeners so that user changes during
// execution of this method will have no effect.
fixListeners(false);
JSlider source= (JSlider)e.getSource();
if (source.equals(HSlider) || source.equals(SSlider) ||
source.equals(VSlider)) {
double H= (double)HSlider.getValue() / 100.0;
double S= (double)SSlider.getValue() / 100.0;
double V= (double)VSlider.getValue() / 100.0;
hsv= new HSV(H, S, V);
rgb= A4Methods.convertHSVtoRGB(hsv);
cmyk= A4Methods.convertRGBtoCMYK(rgb);
}
else if (source.equals(RSlider) || source.equals(GSlider) ||
source.equals(BSlider)) {
int R= (int) Math.round(RSlider.getValue() / 100.0);
int G= (int) Math.round(GSlider.getValue() / 100.0);
int B= (int) Math.round(BSlider.getValue() / 100.0);
rgb= new Color(R, G, B);
hsv= A4Methods.convertRGBtoHSV(rgb);
cmyk= A4Methods.convertRGBtoCMYK(rgb);
}
else if (source.equals(CSlider) || source.equals(MSlider) ||
source.equals(YSlider) || source.equals(KSlider)) {
double C= CSlider.getValue() / 100.0;
double M= MSlider.getValue() / 100.0;
double Y= YSlider.getValue() / 100.0;
double K= KSlider.getValue() / 100.0;
cmyk= new CMYK(C, M, Y, K);
rgb= A4Methods.convertCMYKtoRGB(cmyk);
hsv= A4Methods.convertRGBtoHSV(rgb);
}
else return; // event was not a change in a slider
setSliders(rgb, hsv, cmyk);
setColorPanels(rgb, hsv, cmyk);
// Add the listeners for the sliders
fixListeners(true);
}
/** Set the RGB, HSV, CMYK sliders based on rgb, hsv, and cmyk. */
public void setSliders(Color rgb, HSV hsv, CMYK cmyk) {
RSlider.setValue(rgb.getRed() * 100);
GSlider.setValue(rgb.getGreen() * 100);
BSlider.setValue(rgb.getBlue() * 100);
HSlider.setValue((int)(hsv.hue() * 100.0));
SSlider.setValue((int)(hsv.sat() * 100.0));
VSlider.setValue((int)(hsv.val() * 100.0));
CSlider.setValue((int)(cmyk.cyan() * 100.0));
MSlider.setValue((int)(cmyk.magenta() * 100.0));
YSlider.setValue((int)(cmyk.yellow() * 100.0));
KSlider.setValue((int)(cmyk.black() * 100.0));
}
/** Set background colors and the text in the color window and
* complementary color window, based on rgb, hsv, and cmyk. Put
* the rgb in the title.
*/
public void setColorPanels(Color rgb, HSV hsv, CMYK cmyk) {
image.setBackground(rgb);
Color compRgb= A4Methods.complementRGB(rgb);
compImage.setBackground(compRgb);
imageLabel.setForeground(compRgb);
imageLabel.setText(" Color
RGB: " + A4Methods.toString(rgb) +
"
CMYK: " + A4Methods.toString(cmyk) +
"
HSV: " + A4Methods.toString(hsv) + "
" +
" R,G,B sliders in: 0..255
" +
" C,M,Y,K sliders: 0 to 100%
" +
" H slider: 0 <= H < 360 degrees
" +
" S,V sliders: 0 <= S,V <= 1" + "" );
compImageLabel.setForeground(rgb);
HSV compHsv= A4Methods.convertRGBtoHSV(compRgb);
CMYK compCmyk= A4Methods.convertRGBtoCMYK(compRgb);
compImageLabel.setText(" Complementary Color
RGB: " +
A4Methods.toString(compRgb) +
"
CMYK: " + A4Methods.toString(compCmyk) +
"
HSV: " + A4Methods.toString(compHsv) + "
" +
" R,G,B sliders in: 0..255
" +
" C,M,Y,K sliders: 0 to 100%
" +
" H slider: 0 <= H < 360 degrees
" +
" S,V sliders: 0 <= S,V <= 1" +
"");
jf.setTitle("Color RGB: " + A4Methods.toString(rgb));
}
/** Process a click on the inRGB, inCMYK, or inHSV buttons. The
* appropriate fields are read in, the GUI is set to that color,
* and the other color models are set apropriately.
*/
public void actionPerformed(ActionEvent e) {
// Remove listeners so that user changes during
// execution of this method will have no effect.
fixListeners(false);
Color rgb;
HSV hsv;
CMYK cmyk;
if (e.getSource() == inputrgb) {
int r= getInt(rfield.getText());
int g= getInt(gfield.getText());
int b= getInt(bfield.getText());
rfield.setText("" + r);
gfield.setText("" + g);
bfield.setText("" + b);
rgb= new Color(r, g, b);
hsv= A4Methods.convertRGBtoHSV(rgb);
cmyk= A4Methods.convertRGBtoCMYK(rgb);
} else if (e.getSource() == inputcmyk) {
double c= getDouble100(cfield.getText());
double m= getDouble100(mfield.getText());
double y= getDouble100(yfield.getText());
double k= getDouble100(kfield.getText());
cfield.setText(A4Methods.roundTo5(c));
mfield.setText(A4Methods.roundTo5(m));
yfield.setText(A4Methods.roundTo5(y));
kfield.setText(A4Methods.roundTo5(k));
cmyk= new CMYK(c, m, y, k);
rgb= A4Methods.convertCMYKtoRGB(cmyk);
hsv= A4Methods.convertRGBtoHSV(rgb);
} else {
double h= getDouble360(hfield.getText());
double s= getDouble(sfield.getText());
double v= getDouble(vfield.getText());
hsv= new HSV(h, s, v);
rgb= A4Methods.convertHSVtoRGB(hsv);
cmyk= A4Methods.convertRGBtoCMYK(rgb);
hfield.setText(A4Methods.roundTo5(h));
sfield.setText(A4Methods.roundTo5(s));
vfield.setText(A4Methods.roundTo5(v));
}
setColorPanels(rgb, hsv, cmyk);
setSliders(rgb, hsv, cmyk);
// Add the listeners for the sliders
fixListeners(true);
}
/** Yields: if s is not an int, 0 else max(0, min(255, s). */
public static int getInt(String s) {
try {
int i= Integer.parseInt(s.trim());
return Math.max(0, Math.min(255, i));
} catch (NumberFormatException e) {
return 0;
}
}
/** Yields: if s is not a double, 0 else max(0.0, min(1.0, s). */
public static double getDouble(String s) {
try {
double d= Double.parseDouble(s.trim());
return Math.max(0.0, Math.min(1.0, d));
} catch (NumberFormatException e) {
return 0.0;
}
}
/** Yields: if s is not a double, 0.0 else max(0.0, min(100.0, s). */
public static double getDouble100(String s) {
try {
double d= Double.parseDouble(s.trim());
return Math.max(0.0, Math.min(100.0, d));
} catch (NumberFormatException e) {
return 0.0;
}
}
/** Yields: if s is not a double, 0 else max(0.0, min(359.9, s). */
public static double getDouble360(String s) {
try {
double d= Double.parseDouble(s.trim());
return Math.max(0.0, Math.min(359.9, d));
} catch (NumberFormatException e) {
return 0.0;
}
}
}