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; } } }