package graphics; import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; /** * Class for simple graphics example. The program provides a surface on * which the user can draw rectangles by clicking and dragging. * * @author B.L. Massingill */ public class SimpleDrawX { /** * Creates and displays GUI. * (I could also have put this code in a constructor.) */ private static void createAndShowGUI() { // basic GUI setup JFrame theFrame = new JFrame("Drawing Example"); // set what should happen when window is closed theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // add panel that supports drawing as described final DrawingPanel drawPanel = new DrawingPanel(); theFrame.add(drawPanel, BorderLayout.CENTER); // add a "clear" button JPanel buttonPanel = new JPanel(new FlowLayout()); JButton clearButton = new JButton("Clear"); clearButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { drawPanel.clear(); drawPanel.repaint(); } }); buttonPanel.add(clearButton); theFrame.add(buttonPanel, BorderLayout.SOUTH); // set size theFrame.setSize(600, 400); // make visible theFrame.setVisible(true); } /** * Main method. */ public static void main(String[] args) { // do this in the way recommended as thread-safe SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } // ---- classes ---- /** * Class for rectangle. */ private static class SimpleRectangle { public final int left; public final int top; public final int width; public final int height; public SimpleRectangle(int l, int t, int w, int h) { left = l; top = t; width = w; height = h; } } /** * Class for "drawing panel". */ private static class DrawingPanel extends JPanel { /** * Constructor. */ public DrawingPanel() { // add listeners for various mouse events addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { onMousePressed(e); } public void mouseReleased(MouseEvent e) { onMouseReleased(e); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { onMouseDragged(e); } }); // reset everything clear(); } /** * Clear panel. */ public void clear() { rectangles = new ArrayList<SimpleRectangle>(); selectedPoint = null; dragPoint = null; } /** * "Paint" panel. This is where "custom graphics" is done. * @param g graphics context on which to perform drawing */ public void paintComponent(Graphics g) { // paint background and get Graphics2D version of g super.paintComponent(g); // paint completed rectangles int nextColor = 0; for (SimpleRectangle r : rectangles) { g.setColor(colors[nextColor]); g.fillRect(r.left, r.top, r.width, r.height); nextColor = (nextColor + 1) % colors.length; } // paint something indicating shape-in-progress if ((selectedPoint != null) && (dragPoint != null)) { g.setColor(Color.black); SimpleRectangle outline = makeRectangle(selectedPoint, dragPoint); g.drawRect(outline.left, outline.top, outline.width, outline.height); } } /** * Respond to "mouse pressed" event (by saving the clicked-on * point so we can use it later to construct a rectangle). * @param e object describing the event */ private void onMousePressed(MouseEvent e) { selectedPoint = e.getPoint(); } /** * Respond to "mouse released" event (by constructing a rectangle * using the point saved on a "mouse pressed" event). * @param e object describing the event */ private void onMouseReleased(MouseEvent e) { if (selectedPoint != null) { SimpleRectangle r = makeRectangle(selectedPoint, e.getPoint()); rectangles.add(r); selectedPoint = null; dragPoint = null; } repaint(); } /** * Respond to "mouse dragged" event (by showing an outline of the * rectangle that would be added if the mouse were released). * @param e object describing the event */ private void onMouseDragged(MouseEvent e) { dragPoint = e.getPoint(); repaint(); } /** * Construct shape using p1 and p2 as diagonally-opposite corners. * @param p1 one point * @param p2 the other point * @return rectangle */ private SimpleRectangle makeRectangle(Point p1, Point p2) { return new SimpleRectangle( Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y)); } // ---- variables ---- // colors to cycle through private static Color[] colors = new Color[] { Color.yellow, Color.red, Color.blue, Color.green }; private ArrayList<SimpleRectangle> rectangles; private Point selectedPoint; private Point dragPoint; } }