import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Paint { private static PaintPanel p; // actual drawing area, using mouse (MouseListener) private static GuiPanel gp; // for GUI selections (JRadioButtons, JButtons) public static void main(String[] args) { JFrame f=new JFrame(); f.setSize(800,800); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel p1=new JPanel(new BorderLayout()); // add the two panels (p and gp) to a panel to insert p=new PaintPanel(); // into this JFrame gp=new GuiPanel(); p1.add(p,BorderLayout.CENTER); p1.add(gp,BorderLayout.EAST); f.add(p1); f.setVisible(true); } // the following class implements one of the two JPanels. In this case, it will be our GUI control panel // using JButtons for clearing the screen, undoing the last action, and quitting, and JRadioButtons to // select the Color and shape of object to draw private static class GuiPanel extends JPanel implements ActionListener { private JButton clear,undo,quit; // these JButtons and JRadioButtons are our GUI controls private JRadioButton red, green, blue, black; private JRadioButton line, oval, rect; public GuiPanel() // constructor sets up the ActionListener for the JButtons { // only, instantiates all of these objects and inserts them clear=new JButton("clear"); // into JPanels for a decent appearance undo=new JButton("undo"); quit=new JButton("quit"); clear.addActionListener(this); undo.addActionListener(this); quit.addActionListener(this); red=new JRadioButton("red"); // JRadioButtons will not have their own listeners, we blue=new JRadioButton("blue"); // will test to see what is selected whenever the mouse green=new JRadioButton("green"); // is used to draw a new shape black=new JRadioButton("black"); line=new JRadioButton("line"); oval=new JRadioButton("oval"); rect=new JRadioButton("rectangle"); ButtonGroup b1=new ButtonGroup(); // b1 for the 4 color JRadioButtons b1.add(red); b1.add(green); b1.add(blue); b1.add(black); ButtonGroup b2=new ButtonGroup(); // b2 for the 3 shape JRadioButtons b2.add(line); b2.add(rect); b2.add(oval); JPanel p1=new JPanel(new GridLayout(3,1)); // the 3 JButtons in one JPanel p1.add(clear); p1.add(undo); p1.add(quit); JPanel p2=new JPanel(new GridLayout(4,1)); // the 4 color JRadioButtons in one JPanel p2.add(red); p2.add(green); p2.add(blue); p2.add(black); JPanel p3=new JPanel(new GridLayout(3,1)); // the 3 shape JRadioButtons in one JPanel p3.add(line); p3.add(oval); p3.add(rect); JPanel p4=new JPanel(new BorderLayout()); // coordinate the 3 JPanels into 1 JPanel going across p4.add(p1,BorderLayout.WEST); p4.add(p2,BorderLayout.CENTER); p4.add(p3,BorderLayout.EAST); add(p4); } public void actionPerformed(ActionEvent e) // when a JButton is clicked... { if(e.getSource()==quit) System.exit(0); // on quit, exit the program else if(e.getSource()==clear) // on clear, call JPanel p's clear method p.clear(); else if(e.getSource()==undo) // on undo, call JPanel p's undo method p.undo(); } public Color getColor() // we get called here from p when the user has released the mouse { // to draw a new shape, p needs to get access to the selected Color if(red.isSelected()) return Color.red; // return the Color of the JRadioButton selected else if(green.isSelected()) return Color.green; else if(blue.isSelected()) return Color.blue; else return Color.black; } public int getType() // we get called here from p when the user has released the mouse to draw a new { // shape, p needs to get access to the type of shape as selected by the shape JRadioButtons if(line.isSelected()) return 0; else if(oval.isSelected()) return 1; else return 2; } } // this JPanel will be used for drawing (through Graphics/paintComponent) and implement MouseListener so that // the user can control drawing through the mouse private static class PaintPanel extends JPanel implements MouseListener { private class MyShape // nested inner class to define a shape to be drawn, we limit this to just { // lines, ovals and rectangles. If we wanted to also allow Strings we would have private int x1,x2,y1,y2; // to overload the constructor to allow for one with x, y, String and add private Color c; // a JTextField to the GUI. This makes the program somewhat more complicated private int type; // all Shapes have an x1,y1 coordinate, a color and a type, also x2,y2 is used to indicate public MyShape(int x1, int y1, int x2, int y2, Color c, int type) // where the line is drawn to, or how big the { // bounding box should be this.x1=x1; // initialize all of this shape's attributes this.x2=x2; this.y1=y1; this.y2=y2; this.c=c; this.type=type; } public void draw(Graphics g) // tell this shape to draw itself on g { g.setColor(c); int mx,my; mx=Math.min(x1,x2); // mx, my is used in case the user has moved the mouse up or left giving my=Math.min(y1,y2); // y2 or x2 values < y1 or x1 or both, needed for ovals and rectangles if(type==0) g.drawLine(x1,y1,x2,y2); else if(type==1) g.fillOval(mx,my,Math.abs(x1-x2),Math.abs(y1-y2)); // use abs to ensure that the size is not negative else if(type==2) g.fillRect(mx,my,Math.abs(x1-x2),Math.abs(y1-y2)); } } // here is the body of the PaintPanel class // our instance data private MyShape[] s; // the shapes we will have drawn private int num; // the number of shapes currently to draw private int x1,x2,y1,y2; // the mouse coordinates for when we press the mouse button or release it public PaintPanel() // PaintPanel's constructor just initializes instance data and adds a mouse listener { s=new MyShape[1000]; // we'll assume no more than 1000 shapes will be drawn num=0; x1=x2=y1=y2=-1; // initialize these to -1 just to have a value for them addMouseListener(this); } public void clear() // this is called from the GuiPanel class gp when the Clear JButton is clicked { num=0; // to clear, reset num to 0 so that our for loop does not iterate through the repaint(); // s array to draw anything, and then call the paintComponent method } public void undo() // this is called from the GuiPanel class gp when the Undo JButton is clicked { if(num>0) // make sure num isn't already 0 or we can wind up with a negative number for num leading { // to an exception num--; // we decrement num to indicate that the for loop in paintComponent should not draw the repaint(); // most recently added shape } } public void mousePressed(MouseEvent e) // when mouse button is pressed, record its x,y coordinate in x1,y1 { x1=e.getX(); y1=e.getY(); } public void mouseReleased(MouseEvent e) // when released, record its x,y coordinate in x2,y2 and get the { // JRadioButton information from the GuiPanel (gp) to create a new MyShape Color c=gp.getColor(); int type=gp.getType(); x2=e.getX(); y2=e.getY(); s[num]=new MyShape(x1,y1,x2,y2,c,type); // the new MyShape is added to s at position num and we then increment num++; // num to indicate another shape has been added repaint(); // now redraw all of the shapes } public void mouseClicked(MouseEvent e) {} // don't need to implement these public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void paintComponent(Graphics g) { super.paintComponent(g); // blank the Graphics area for(int i=0;i