import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * This program demonstrates the effect of using different Strokes when * drawing lines and rectangles. Fifteen small panels are shown, in three * rows and five columns. Each panel uses a different stroke. The stroke * widths are 1, 2, 5, 10, or 20, depending on the column. The first row * uses the default values of the stroke for cap and join. The second row * uses BasicStroke.CAP_ROUND and BasicStroke.JOIN_ROUND. The third row * uses BasicStroke.CAP_BUTT and BasicStroke.JOIN_BEVEL. In addition the * third row uses a dash pattern. The program illustrates antialiasing, * which is off in the first row and on in the second and third rows. * This class has a main() routine and so can be run as an application. */ public class StrokeDemo extends JPanel { /** * The main routine simply opens a window that shows a StrokeDemo panel. */ public static void main(String[] args) { JFrame window = new JFrame("Click and Drag; Right-click for Rectangles"); StrokeDemo content = new StrokeDemo(); window.setContentPane(content); window.pack(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); window.setLocation( (screenSize.width - window.getWidth())/2, (screenSize.height - window.getHeight())/2 ); window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); window.setVisible(true); } /** * Each of the 15 panels in the program is an object of type Display. */ private class Display extends JPanel { Stroke stroke; // The stroke used for drawing in this panel. boolean antialiased; // Should antialiasing be used? boolean drawLine = true; // Should a line be drawn, or a rectangle? int x1, y1, x2, y2; // Endpoints of line or corners of rectangle. Display(Stroke s, boolean a) { stroke = s; antialiased = a; x1 = y1 = 15; x2 = 80; y2 = 85; setPreferredSize(new Dimension(100,100)); setBackground(Color.WHITE); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setStroke(stroke); if (antialiased) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } if (drawLine) g2.drawLine(x1,y1,x2,y2); else { int a = Math.min(x1,x2); int b = Math.min(y1,y2); int w = Math.abs(x1 - x2); int h = Math.abs(y1 - y2); g2.drawRect(a,b,w,h); } } } /** * An object of type MouseHandler is used as a MouseListener and MouseMotionListener * on each of the Display panels in the main panel. When the user clicks and drags * on ANY panel, ALL panels are repainted to show a line or rectangle between the * start point of the mouse drag operation and the current point. If a right-mouse * click starts the draw operation (Command-click on Mac), a rectangle is drawn; * otherwise a line is drawn. */ private class MouseHandler implements MouseListener, MouseMotionListener { public void mousePressed(MouseEvent e) { for (int i = 0; i < 5; i++) for (int j = 0; j < 3; j++) { displays[i][j].x1 = e.getX(); displays[i][j].x2 = e.getX(); displays[i][j].y1 = e.getY(); displays[i][j].y2 = e.getY(); displays[i][j].drawLine = ! e.isMetaDown(); displays[i][j].repaint(); } } public void mouseDragged(MouseEvent e) { for (int i = 0; i < 5; i++) for (int j = 0; j < 3; j++) { displays[i][j].x2 = e.getX(); displays[i][j].y2 = e.getY(); displays[i][j].repaint(); } } public void mouseReleased(MouseEvent e) { } public void mouseMoved(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } } /** * The arrays of Displays that represent the 15 small panels in the program. */ private Display[][] displays = new Display[5][3]; /** * The constructor creates and lays out the 15 display panels in a grid. * Each panel is created with a different Stroke. The first row of panels * is not antialiased, but the other two rows are. */ public StrokeDemo() { setLayout(new GridLayout(3,5,3,3)); setBorder(BorderFactory.createLineBorder(Color.GRAY,3)); setBackground(Color.GRAY); displays[0][0] = new Display(new BasicStroke(1), false); displays[1][0] = new Display(new BasicStroke(2), false); displays[2][0] = new Display(new BasicStroke(5), false); displays[3][0] = new Display(new BasicStroke(10), false); displays[4][0] = new Display(new BasicStroke(20), false); displays[0][1] = new Display(new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), true); displays[1][1] = new Display(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), true); displays[2][1] = new Display(new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), true); displays[3][1] = new Display(new BasicStroke(10, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), true); displays[4][1] = new Display(new BasicStroke(20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND), true); displays[0][2] = new Display(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, new float[] {5,5}, 0), true); displays[1][2] = new Display(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, new float[] {5,5}, 0), true); displays[2][2] = new Display(new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, new float[] {5,5}, 0), true); displays[3][2] = new Display(new BasicStroke(10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, new float[] {5,5}, 0), true); displays[4][2] = new Display(new BasicStroke(20, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, new float[] {5,5}, 0), true); MouseHandler listener = new MouseHandler(); for (int row = 0; row < 3; row++) for (int col = 0; col < 5; col++) { add(displays[col][row]); displays[col][row].addMouseListener(listener); displays[col][row].addMouseMotionListener(listener); } } }