/*
* Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.com/javaexamples2.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
/**
* This JFrame subclass is a simple "paint" application.
*/
public class Scribble extends JFrame {
/**
* The main method instantiates an instance of the class, sets it size, and
* makes it visible on the screen
*/
public static void main(String[] args) {
Scribble scribble = new Scribble();
scribble.setSize(500, 300);
scribble.setVisible(true);
}
// The scribble application relies on the ScribblePane2 component developed
// earlier. This field holds the ScribblePane2 instance it uses.
ScribblePane2 scribblePane;
/**
* This constructor creates the GUI for this application.
*/
public Scribble() {
super("Scribble"); // Call superclass constructor and set window title
// Handle window close requests
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
// All content of a JFrame (except for the menubar) goes in the
// Frame's internal "content pane", not in the frame itself.
// The same is true for JDialog and similar top-level containers.
Container contentPane = this.getContentPane();
// Specify a layout manager for the content pane
contentPane.setLayout(new BorderLayout());
// Create the main scribble pane component, give it a border, and
// a background color, and add it to the content pane
scribblePane = new ScribblePane2();
scribblePane.setBorder(new BevelBorder(BevelBorder.LOWERED));
scribblePane.setBackground(Color.white);
contentPane.add(scribblePane, BorderLayout.CENTER);
// Create a menubar and add it to this window. Note that JFrame
// handles menus specially and has a special method for adding them
// outside of the content pane.
JMenuBar menubar = new JMenuBar(); // Create a menubar
this.setJMenuBar(menubar); // Display it in the JFrame
// Create menus and add to the menubar
JMenu filemenu = new JMenu("File");
JMenu colormenu = new JMenu("Color");
menubar.add(filemenu);
menubar.add(colormenu);
// Create some Action objects for use in the menus and toolbars.
// An Action combines a menu title and/or icon with an ActionListener.
// These Action classes are defined as inner classes below.
Action clear = new ClearAction();
Action quit = new QuitAction();
Action black = new ColorAction(Color.black);
Action red = new ColorAction(Color.red);
Action blue = new ColorAction(Color.blue);
Action select = new SelectColorAction();
// Populate the menus using Action objects
filemenu.add(clear);
filemenu.add(quit);
colormenu.add(black);
colormenu.add(red);
colormenu.add(blue);
colormenu.add(select);
// Now create a toolbar, add actions to it, and add it to the
// top of the frame (where it appears underneath the menubar)
JToolBar toolbar = new JToolBar();
toolbar.add(clear);
toolbar.add(select);
toolbar.add(quit);
contentPane.add(toolbar, BorderLayout.NORTH);
// Create another toolbar for use as a color palette and add to
// the left side of the window.
JToolBar palette = new JToolBar();
palette.add(black);
palette.add(red);
palette.add(blue);
palette.setOrientation(SwingConstants.VERTICAL);
contentPane.add(palette, BorderLayout.WEST);
}
/** This inner class defines the "clear" action that clears the scribble */
class ClearAction extends AbstractAction {
public ClearAction() {
super("Clear"); // Specify the name of the action
}
public void actionPerformed(ActionEvent e) {
scribblePane.clear();
}
}
/** This inner class defines the "quit" action to quit the program */
class QuitAction extends AbstractAction {
public QuitAction() {
super("Quit");
}
public void actionPerformed(ActionEvent e) {
// Use JOptionPane to confirm that the user really wants to quit
int response = JOptionPane.showConfirmDialog(Scribble.this,
"Really Quit?");
if (response == JOptionPane.YES_OPTION)
System.exit(0);
}
}
/**
* This inner class defines an Action that sets the current drawing color of
* the ScribblePane2 component. Note that actions of this type have icons
* rather than labels
*/
class ColorAction extends AbstractAction {
Color color;
public ColorAction(Color color) {
this.color = color;
putValue(Action.SMALL_ICON, new ColorIcon(color)); // specify icon
}
public void actionPerformed(ActionEvent e) {
scribblePane.setColor(color); // Set current drawing color
}
}
/**
* This inner class implements Icon to draw a solid 16x16 block of the
* specified color. Most icons are instances of ImageIcon, but since we're
* only using solid colors here, it is easier to implement this custom Icon
* type
*/
static class ColorIcon implements Icon {
Color color;
public ColorIcon(Color color) {
this.color = color;
}
// These two methods specify the size of the icon
public int getIconHeight() {
return 16;
}
public int getIconWidth() {
return 16;
}
// This method draws the icon
public void paintIcon(Component c, Graphics g, int x, int y) {
g.setColor(color);
g.fillRect(x, y, 16, 16);
}
}
/**
* This inner class defines an Action that uses JColorChooser to allow the
* user to select a drawing color
*/
class SelectColorAction extends AbstractAction {
public SelectColorAction() {
super("Select Color...");
}
public void actionPerformed(ActionEvent e) {
Color color = JColorChooser.showDialog(Scribble.this,
"Select Drawing Color", scribblePane.getColor());
if (color != null)
scribblePane.setColor(color);
}
}
}
/*
* Copyright (c) 2000 David Flanagan. All rights reserved. This code is from the
* book Java Examples in a Nutshell, 2nd Edition. It is provided AS-IS, WITHOUT
* ANY WARRANTY either expressed or implied. You may study, use, and modify it
* for any non-commercial purpose. You may distribute it non-commercially as
* long as you retain this notice. For a commercial use license, or to purchase
* the book (recommended), visit http://www.davidflanagan.com/javaexamples2.
*/
/**
* A simple JPanel subclass that uses event listeners to allow the user to
* scribble with the mouse. Note that scribbles are not saved or redrawn.
*/
class ScribblePane2 extends JPanel {
public ScribblePane2() {
// Give the component a preferred size
setPreferredSize(new Dimension(450, 200));
// Register a mouse event handler defined as an inner class
// Note the call to requestFocus(). This is required in order for
// the component to receive key events.
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
moveto(e.getX(), e.getY()); // Move to click position
requestFocus(); // Take keyboard focus
}
});
// Register a mouse motion event handler defined as an inner class
// By subclassing MouseMotionAdapter rather than implementing
// MouseMotionListener, we only override the method we're interested
// in and inherit default (empty) implementations of the other methods.
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
lineto(e.getX(), e.getY()); // Draw to mouse position
}
});
// Add a keyboard event handler to clear the screen on key 'C'
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_C)
clear();
}
});
}
/** These are the coordinates of the the previous mouse position */
protected int last_x, last_y;
/** Remember the specified point */
public void moveto(int x, int y) {
last_x = x;
last_y = y;
}
/** Draw from the last point to this point, then remember new point */
public void lineto(int x, int y) {
Graphics g = getGraphics(); // Get the object to draw with
g.setColor(color); // Tell it what color to use
g.drawLine(last_x, last_y, x, y); // Tell it what to draw
moveto(x, y); // Save the current point
}
/**
* Clear the drawing area, using the component background color. This method
* works by requesting that the component be redrawn. Since this component
* does not have a paintComponent() method, nothing will be drawn. However,
* other parts of the component, such as borders or sub-components will be
* drawn correctly.
*/
public void clear() {
repaint();
}
/** This field holds the current drawing color property */
Color color = Color.black;
/** This is the property "setter" method for the color property */
public void setColor(Color color) {
this.color = color;
}
/** This is the property "getter" method for the color property */
public Color getColor() {
return color;
}
}
|