窗口应用程序。

本例在上一版的基础上实现了高亮元素、移动元素、上下文菜单、旋转元素、设置自定义颜色。

1、自定义常量包:

 // Defines application wide constants
package Constants;
import java.awt.*;
import javax.swing.*;
import java.awt.image.BufferedImage; public class SketcherConstants {
// Path for images
public final static String imagePath = "E:/JavaProject/BeginningJava/Images/"; // Toolbar icons
public final static Icon NEW24 = new ImageIcon(imagePath + "New24.gif");
public final static Icon OPEN24 = new ImageIcon(imagePath + "Open24.gif");
public final static Icon SAVE24 = new ImageIcon(imagePath + "Save24.gif");
public final static Icon SAVEAS24 = new ImageIcon(imagePath + "SaveAs24.gif");
public final static Icon PRINT24 = new ImageIcon(imagePath + "Print24.gif"); public final static Icon LINE24 = new ImageIcon(imagePath + "Line24.gif");
public final static Icon RECTANGLE24 = new ImageIcon(imagePath + "Rectangle24.gif");
public final static Icon CIRCLE24 = new ImageIcon(imagePath + "Circle24.gif");
public final static Icon CURVE24 = new ImageIcon(imagePath + "Curve24.gif");
public final static Icon TEXT24 = new ImageIcon(imagePath + "Text24.gif"); public final static Icon RED24 = new ImageIcon(imagePath + "Red24.gif");
public final static Icon GREEN24 = new ImageIcon(imagePath + "Green24.gif");
public final static Icon BLUE24 = new ImageIcon(imagePath + "Blue24.gif");
public final static Icon YELLOW24 = new ImageIcon(imagePath + "Yellow24.gif");
public final static ImageIcon CUSTOM24 = new ImageIcon(new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB)); // Menu item icons
public final static Icon NEW16 = new ImageIcon(imagePath + "new16.gif");
public final static Icon OPEN16 = new ImageIcon(imagePath + "Open16.gif");
public final static Icon SAVE16 = new ImageIcon(imagePath + "Save16.gif");
public final static Icon SAVEAS16 = new ImageIcon(imagePath + "SaveAs16.gif");
public final static Icon PRINT16 = new ImageIcon(imagePath + "print16.gif"); public final static Icon LINE16 = new ImageIcon(imagePath + "Line16.gif");
public final static Icon RECTANGLE16 = new ImageIcon(imagePath + "Rectangle16.gif");
public final static Icon CIRCLE16 = new ImageIcon(imagePath + "Circle16.gif");
public final static Icon CURVE16 = new ImageIcon(imagePath + "Curve16.gif");
public final static Icon TEXT16 = new ImageIcon(imagePath + "Text16.gif"); public final static Icon RED16 = new ImageIcon(imagePath + "Red16.gif");
public final static Icon GREEN16 = new ImageIcon(imagePath + "Green16.gif");
public final static Icon BLUE16 = new ImageIcon(imagePath + "Blue16.gif");
public final static Icon YELLOW16 = new ImageIcon(imagePath + "Yellow16.gif");
public final static ImageIcon CUSTOM16 = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB)); // Element type definitions
public final static int LINE = 101;
public final static int RECTANGLE = 102;
public final static int CIRCLE = 103;
public final static int CURVE = 104;
public final static int TEXT = 105; // Initial conditions
public final static int DEFAULT_ELEMENT_TYPE = LINE;
public final static Color DEFAULT_ELEMENT_COLOR = Color.BLUE;
public final static Color HIGHLIGHT_COLOR = Color.MAGENTA;
public final static Font DEFAULT_FONT = new Font("Serif", Font.BOLD, 12); // Font point size range specification
public final static int POINT_SIZE_MIN = 8; // Minimum font point size
public final static int POINT_SIZE_MAX = 24; // Maximum font point size
public final static int POINT_SIZE_STEP = 2; // Point size step // Operating modes
public final static String NORMAL = "Normal";
public final static String MOVE = "Move";
public final static String ROTATE = "Rotate";
}

2、窗口框架:

 // Frame for the Sketcher application
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D; import static java.awt.event.InputEvent.*;
import static java.awt.Color.*;
import static Constants.SketcherConstants.*;
import static javax.swing.Action.*; @SuppressWarnings("serial")
public class SketcherFrame extends JFrame implements ActionListener {
// Constructor
public SketcherFrame(String title, Sketcher theApp) {
setTitle(title); // Set the window title
this.theApp = theApp; // Save app. object reference
setJMenuBar(menuBar); // Add the menu bar to the window
setDefaultCloseOperation(EXIT_ON_CLOSE); // Default is exit the application setCustomIconColor(CUSTOM16,customColor); // Setup small custom color icon
setCustomIconColor(CUSTOM24,customColor); // Setup large custom color icon
createFileMenu(); // Create the File menu
createElementMenu(); // Create the element menu
createColorMenu(); // Create the element menu
optionsMenu = new JMenu("Options"); // Create options menu
optionsMenu.setMnemonic('O'); // Create shortcut
menuBar.add(optionsMenu); // Add options to menu bar createPopupMenu(); // Create popup // Add the font choice item to the options menu
fontItem = new JMenuItem("Choose font...");
fontItem.addActionListener(this);
optionsMenu.add(fontItem); fontDlg = new FontDialog(this); // Create the font dialog createToolbar();
toolBar.setRollover(true); JMenu helpMenu = new JMenu("Help"); // Create Help menu
helpMenu.setMnemonic('H'); // Create Help shortcut // Add the About item to the Help menu
aboutItem = new JMenuItem("About"); // Create About menu item
aboutItem.addActionListener(this); // Listener is the frame
helpMenu.add(aboutItem); // Add item to menu
menuBar.add(helpMenu); // Add Help menu to menu bar getContentPane().add(toolBar, BorderLayout.NORTH); // Add the toolbar
getContentPane().add(statusBar, BorderLayout.SOUTH); // Add the statusbar
} // Create File menu item actions
private void createFileMenuActions() {
newAction = new FileAction("New", 'N', CTRL_DOWN_MASK);
openAction = new FileAction("Open", 'O', CTRL_DOWN_MASK);
closeAction = new FileAction("Close");
saveAction = new FileAction("Save", 'S', CTRL_DOWN_MASK);
saveAsAction = new FileAction("Save As...");
printAction = new FileAction("Print", 'P', CTRL_DOWN_MASK);
exitAction = new FileAction("Exit", 'X', CTRL_DOWN_MASK); // Initialize the array
FileAction[] actions = {openAction, closeAction, saveAction, saveAsAction, printAction, exitAction};
fileActions = actions; // Add toolbar icons
newAction.putValue(LARGE_ICON_KEY, NEW24);
openAction.putValue(LARGE_ICON_KEY, OPEN24);
saveAction.putValue(LARGE_ICON_KEY, SAVE24);
saveAsAction.putValue(LARGE_ICON_KEY, SAVEAS24);
printAction.putValue(LARGE_ICON_KEY, PRINT24); // Add menu item icons
newAction.putValue(SMALL_ICON, NEW16);
openAction.putValue(SMALL_ICON, OPEN16);
saveAction.putValue(SMALL_ICON, SAVE16);
saveAsAction.putValue(SMALL_ICON,SAVEAS16);
printAction.putValue(SMALL_ICON, PRINT16); // Add tooltip text
newAction.putValue(SHORT_DESCRIPTION, "Create a new sketch");
openAction.putValue(SHORT_DESCRIPTION, "Read a sketch from a file");
closeAction.putValue(SHORT_DESCRIPTION, "Close the current sketch");
saveAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to file");
saveAsAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to a new file");
printAction.putValue(SHORT_DESCRIPTION, "Print the current sketch");
exitAction.putValue(SHORT_DESCRIPTION, "Exit Sketcher");
} // Helper method to set custom icon color
private void setCustomIconColor(ImageIcon icon, Color color) {
BufferedImage image = (BufferedImage)(icon.getImage());
int width = image.getWidth(); // Image width
int indent = width == 16 ? 3 : 2; // Indent for filled rectangle
int rectSize = width - 2*indent; // Filled rectangle size
Graphics2D g2D = image.createGraphics();
g2D.setPaint(color);
g2D.fillRect(indent,indent,rectSize,rectSize); // Fill centered rectangle
if(width == 24) {
TextLayout textLayout = new TextLayout("C", g2D.getFont(), g2D.getFontRenderContext());
Rectangle2D.Float rect = (Rectangle2D.Float)textLayout.getBounds();
g2D.setPaint(new Color(255-color.getRed(),255-color.getGreen(), 255-color.getBlue()));
g2D.drawString("C", (width-rect.width)/2, (width+rect.height)/2);
}
g2D.dispose();
} // Create the File menu
private void createFileMenu() {
JMenu fileMenu = new JMenu("File"); // Create File menu
fileMenu.setMnemonic('F'); // Create shortcut
createFileMenuActions(); // Create Actions for File menu item // Construct the file drop-down menu
fileMenu.add(newAction); // New Sketch menu item
fileMenu.add(openAction); // Open sketch menu item
fileMenu.add(closeAction); // Close sketch menu item
fileMenu.addSeparator(); // Add separator
fileMenu.add(saveAction); // Save sketch to file
fileMenu.add(saveAsAction); // Save As menu item
fileMenu.addSeparator(); // Add separator
fileMenu.add(printAction); // Print sketch menu item
fileMenu.addSeparator(); // Add separator
fileMenu.add(exitAction); // Print sketch menu item
menuBar.add(fileMenu); // Add the file menu
} // Create Element menu actions
private void createElementTypeActions() {
lineAction = new TypeAction("Line", LINE, 'L', CTRL_DOWN_MASK);
rectangleAction = new TypeAction("Rectangle", RECTANGLE, 'R', CTRL_DOWN_MASK);
circleAction = new TypeAction("Circle", CIRCLE,'C', CTRL_DOWN_MASK);
curveAction = new TypeAction("Curve", CURVE,'U', CTRL_DOWN_MASK);
textAction = new TypeAction("Text", TEXT,'T', CTRL_DOWN_MASK); // Initialize the array
TypeAction[] actions = {lineAction, rectangleAction, circleAction, curveAction, textAction};
typeActions = actions; // Add toolbar icons
lineAction.putValue(LARGE_ICON_KEY, LINE24);
rectangleAction.putValue(LARGE_ICON_KEY, RECTANGLE24);
circleAction.putValue(LARGE_ICON_KEY, CIRCLE24);
curveAction.putValue(LARGE_ICON_KEY, CURVE24);
textAction.putValue(LARGE_ICON_KEY, TEXT24); // Add menu item icons
lineAction.putValue(SMALL_ICON, LINE16);
rectangleAction.putValue(SMALL_ICON, RECTANGLE16);
circleAction.putValue(SMALL_ICON, CIRCLE16);
curveAction.putValue(SMALL_ICON, CURVE16);
textAction.putValue(SMALL_ICON, TEXT16); // Add tooltip text
lineAction.putValue(SHORT_DESCRIPTION, "Draw lines");
rectangleAction.putValue(SHORT_DESCRIPTION, "Draw rectangles");
circleAction.putValue(SHORT_DESCRIPTION, "Draw circles");
curveAction.putValue(SHORT_DESCRIPTION, "Draw curves");
textAction.putValue(SHORT_DESCRIPTION, "Draw text");
} // Create the Elements menu
private void createElementMenu() {
createElementTypeActions();
elementMenu = new JMenu("Elements"); // Create Elements menu
elementMenu.setMnemonic('E'); // Create shortcut
createRadioButtonDropDown(elementMenu, typeActions, lineAction);
menuBar.add(elementMenu); // Add the element menu
} // Create Color menu actions
private void createElementColorActions() {
redAction = new ColorAction("Red", RED, 'R', CTRL_DOWN_MASK|ALT_DOWN_MASK);
yellowAction = new ColorAction("Yellow", YELLOW, 'Y', CTRL_DOWN_MASK|ALT_DOWN_MASK);
greenAction = new ColorAction("Green", GREEN, 'G', CTRL_DOWN_MASK|ALT_DOWN_MASK);
blueAction = new ColorAction("Blue", BLUE, 'B', CTRL_DOWN_MASK|ALT_DOWN_MASK);
customAction = new ColorAction("Custom...", BLUE, 'C', CTRL_DOWN_MASK|ALT_DOWN_MASK); // Initialize the array
ColorAction[] actions = {redAction, greenAction, blueAction, yellowAction, customAction};
colorActions = actions; // Add toolbar icons
redAction.putValue(LARGE_ICON_KEY, RED24);
greenAction.putValue(LARGE_ICON_KEY, GREEN24);
blueAction.putValue(LARGE_ICON_KEY, BLUE24);
yellowAction.putValue(LARGE_ICON_KEY, YELLOW24);
customAction.putValue(LARGE_ICON_KEY, CUSTOM24); // Add menu item icons
redAction.putValue(SMALL_ICON, RED16);
greenAction.putValue(SMALL_ICON, GREEN16);
blueAction.putValue(SMALL_ICON, BLUE16);
yellowAction.putValue(SMALL_ICON, YELLOW16);
customAction.putValue(SMALL_ICON, CUSTOM16); // Add tooltip text
redAction.putValue(SHORT_DESCRIPTION, "Draw in red");
greenAction.putValue(SHORT_DESCRIPTION, "Draw in green");
blueAction.putValue(SHORT_DESCRIPTION, "Draw in blue");
yellowAction.putValue(SHORT_DESCRIPTION, "Draw in yellow");
customAction.putValue(SHORT_DESCRIPTION, "Draw in custom color");
} // Create the Color menu
private void createColorMenu() {
createElementColorActions();
colorMenu = new JMenu("Color"); // Create Elements menu
colorMenu.setMnemonic('C'); // Create shortcut
createRadioButtonDropDown(colorMenu, colorActions, blueAction);
menuBar.add(colorMenu); // Add the color menu
} // Menu creation helper
private void createRadioButtonDropDown(JMenu menu, Action[] actions, Action selected) {
ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem item = null;
for(Action action : actions) {
group.add(menu.add(item = new JRadioButtonMenuItem(action)));
if(action == selected) {
item.setSelected(true); // This is default selected
}
}
} // Create pop-up menu
private void createPopupMenu() {
// Element menu items
popup.add(new JMenuItem(lineAction));
popup.add(new JMenuItem(rectangleAction));
popup.add(new JMenuItem(circleAction));
popup.add(new JMenuItem(curveAction));
popup.add(new JMenuItem(textAction)); popup.addSeparator(); // Color menu items
popup.add(new JMenuItem(redAction));
popup.add(new JMenuItem(yellowAction));
popup.add(new JMenuItem(greenAction));
popup.add(new JMenuItem(blueAction));
popup.add(new JMenuItem(customAction));
} // Create toolbar buttons on the toolbar
private void createToolbar() {
for(FileAction action: fileActions){
if(action != exitAction && action != closeAction)
addToolbarButton(action); // Add the toolbar button
}
toolBar.addSeparator(); // Create Color menu buttons
for(ColorAction action:colorActions){
addToolbarButton(action); // Add the toolbar button
} toolBar.addSeparator(); // Create Elements menu buttons
for(TypeAction action:typeActions){
addToolbarButton(action); // Add the toolbar button
}
} // Create and add a toolbar button
private void addToolbarButton(Action action) {
JButton button = new JButton(action); // Create from Action
button.setBorder(BorderFactory.createCompoundBorder( // Add button border
new EmptyBorder(2,5,5,2), // Outside border
BorderFactory.createRaisedBevelBorder())); // Inside border
button.setHideActionText(true); // No label on the button
toolBar.add(button); // Add the toolbar button
} // Return the current drawing color
public Color getElementColor() {
return elementColor;
} // Return the current element type
public int getElementType() {
return elementType;
} // Return current text font
public Font getFont() {
return textFont;
} // Method to set the current font
public void setFont(Font font) {
textFont = font;
} // Retrieve the pop-up menu
public JPopupMenu getPopup() {
return popup;
} // Set radio button menu checks
private void setChecks(JMenu menu, Object eventSource) {
if(eventSource instanceof JButton){
JButton button = (JButton)eventSource;
Action action = button.getAction();
for(int i = 0 ; i<menu.getItemCount() ; ++i) {
JMenuItem item = menu.getItem(i);
item.setSelected(item.getAction() == action);
}
}
} // Handle About menu events
public void actionPerformed(ActionEvent e) {
if(e.getSource() == aboutItem) {
// Create about dialog with the app window as parent
JOptionPane.showMessageDialog(this, // Parent
"Sketcher Copyright Ivor Horton 2011", // Message
"About Sketcher", // Title
JOptionPane.INFORMATION_MESSAGE); // Message type
} else if(e.getSource() == fontItem) { // Set the dialog window position
fontDlg.setLocationRelativeTo(this);
fontDlg.setVisible(true); // Show the dialog
}
} // Inner class defining Action objects for File menu items
class FileAction extends AbstractAction {
// Create action with a name
FileAction(String name) {
super(name);
} // Create action with a name and accelerator
FileAction(String name, char ch, int modifiers) {
super(name);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); // Now find the character to underline
int index = name.toUpperCase().indexOf(ch);
if(index != -1) {
putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index);
}
} // Event handler
public void actionPerformed(ActionEvent e) {
// You will add action code here eventually...
}
} // Inner class defining Action objects for Element type menu items
class TypeAction extends AbstractAction {
// Create action with just a name property
TypeAction(String name, int typeID) {
super(name);
this.typeID = typeID;
} // Create action with a name and an accelerator
private TypeAction(String name,int typeID, char ch, int modifiers) {
this(name, typeID);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); // Now find the character to underline
int index = name.toUpperCase().indexOf(ch);
if(index != -1) {
putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index);
}
} public void actionPerformed(ActionEvent e) {
elementType = typeID;
setChecks(elementMenu, e.getSource());
statusBar.setTypePane(typeID);
} private int typeID;
} // Handles color menu items
class ColorAction extends AbstractAction {
// Create an action with a name and a color
public ColorAction(String name, Color color) {
super(name);
this.color = color;
} // Create an action with a name, a color, and an accelerator
public ColorAction(String name, Color color, char ch, int modifiers) {
this(name, color);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); // Now find the character to underline
int index = name.toUpperCase().indexOf(ch);
if(index != -1) {
putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index);
}
} public void actionPerformed(ActionEvent e) {
if(this == customAction) {
// This could be a new custom color
Color newColor = JColorChooser.showDialog(SketcherFrame.this, "Select Custom Color", customColor);
if(newColor != null) {
elementColor = customColor = newColor; // Setup small custom color icons
setCustomIconColor(CUSTOM16,customColor);
setCustomIconColor(CUSTOM24,customColor);
toolBar.repaint(); // Repaint the toolbar
}
} else {
// This is just a standard color change
elementColor = color;
}
statusBar.setColorPane(elementColor); // Update the status bar
setChecks(colorMenu, e.getSource()); // Set Color menu checks
} private Color color;
} // File actions
private FileAction newAction, openAction, closeAction, saveAction, saveAsAction, printAction, exitAction;
private FileAction[] fileActions; // File actions as an array // Element type actions
private TypeAction lineAction, rectangleAction, circleAction, curveAction, textAction;
private TypeAction[] typeActions; // Type actions as an array // Element color actions
private ColorAction redAction, yellowAction,greenAction, blueAction, customAction;
private ColorAction[] colorActions; // Color actions as an array private JMenuBar menuBar = new JMenuBar(); // Window menu bar
private JMenu elementMenu; // Elements menu
private JMenu colorMenu; // Color menu
private JMenu optionsMenu; // Options menu private StatusBar statusBar = new StatusBar(); // Window status bar
private FontDialog fontDlg; // The font dialog private JMenuItem aboutItem; // About menu item
private JMenuItem fontItem; // Font chooser menu item private JPopupMenu popup = new JPopupMenu("General"); // Window pop-up
private Color elementColor = DEFAULT_ELEMENT_COLOR; // Current element color
private Color customColor = DEFAULT_ELEMENT_COLOR; // Current custom color
private int elementType = DEFAULT_ELEMENT_TYPE; // Current element type
private Font textFont = DEFAULT_FONT; // Default font for text elements
private JToolBar toolBar = new JToolBar(); // Window toolbar
private Sketcher theApp; // The application object
}

3、元素类:

 import java.awt.*;
import java.io.Serializable;
import static Constants.SketcherConstants.*;
import java.awt.geom.*; public abstract class Element implements Serializable{ public Element(Point position, Color color) {
this.position = new Point(position);
this.color = color;
} protected Element(Color color) {
this.color = color;
} // Returns the color of the element
public Color getColor() {
return color;
} // Returns the position of the element
public Point getPosition() {
return position;
} // Returns the bounding rectangle enclosing an element boundary
public java.awt.Rectangle getBounds() {
AffineTransform at = AffineTransform.getTranslateInstance(position.x, position.y);
at.rotate(angle);
at.translate(-position.x, -position.y);
return at.createTransformedShape(bounds).getBounds();
} // Set or reset highlight color
public void setHighlighted(boolean highlighted) {
this.highlighted = highlighted;
} // Create a new element
public static Element createElement(int type, Color color, Point start, Point end) {
switch(type) {
case LINE:
return new Element.Line(start, end, color);
case RECTANGLE:
return new Rectangle(start, end, color);
case CIRCLE:
return new Circle(start, end, color);
case CURVE:
return new Curve(start, end, color);
default:
assert false; // We should never get to here
}
return null;
} // Draw a geometric element of type Shape
protected void draw(Graphics2D g2D, Shape element) {
g2D.setPaint(highlighted ? Color.MAGENTA : color); // Set the element color
AffineTransform old = g2D.getTransform(); // Save copy of current transform
g2D.translate((double)position.x, (double)position.y); // Add a translation to current transform
g2D.rotate(angle); // Rotate about position
g2D.draw(element); // Draw the element
g2D.setTransform(old); // Restore original transform
} // Move an element
public void move(int deltaX, int deltaY) {
position.translate(deltaX, deltaY);
bounds.translate(deltaX, deltaY);
} // Rotate an element
public void setRotation(double angle) {
this.angle = angle;
} // Get the rotation angle
public double getRotation() {
return angle;
} // Nested class defining a line
public static class Line extends Element {
public Line(Point start, Point end, Color color) {
super(start, color);
line = new Line2D.Double(origin.x, origin.y, end.x - position.x, end.y - position.y);
bounds = new java.awt.Rectangle(
Math.min(start.x ,end.x), Math.min(start.y, end.y),
Math.abs(start.x - end.x)+1, Math.abs(start.y - end.y)+1);
} // Change the end point for the line
public void modify(Point start, Point last) {
line.x2 = last.x - position.x;
line.y2 = last.y - position.y;
bounds = new java.awt.Rectangle(
Math.min(start.x ,last.x), Math.min(start.y, last.y),
Math.abs(start.x - last.x)+1, Math.abs(start.y - last.y)+1);
} // Display the line
public void draw(Graphics2D g2D) {
draw(g2D, line); // Draw the line
}
private Line2D.Double line;
private final static long serialVersionUID = 1001L;
} // Nested class defining a rectangle
public static class Rectangle extends Element {
public Rectangle(Point start, Point end, Color color) {
super(new Point(Math.min(start.x, end.x), Math.min(start.y, end.y)), color);
rectangle = new Rectangle2D.Double(
origin.x, origin.y, // Top-left corner
Math.abs(start.x - end.x), Math.abs(start.y - end.y)); // Width & height
bounds = new java.awt.Rectangle(
Math.min(start.x ,end.x), Math.min(start.y, end.y),
Math.abs(start.x - end.x)+1, Math.abs(start.y - end.y)+1);
} // Display the rectangle
public void draw(Graphics2D g2D) {
draw(g2D, rectangle); // Draw the rectangle
} // Method to redefine the rectangle
public void modify(Point start, Point last) {
bounds.x = position.x = Math.min(start.x, last.x);
bounds.y = position.y = Math.min(start.y, last.y);
rectangle.width = Math.abs(start.x - last.x);
rectangle.height = Math.abs(start.y - last.y);
bounds.width = (int)rectangle.width + 1;
bounds.height = (int)rectangle.height + 1;
} private Rectangle2D.Double rectangle;
private final static long serialVersionUID = 1001L;
} // Nested class defining a circle
public static class Circle extends Element {
public Circle(Point center, Point circum, Color color) {
super(color); // Radius is distance from center to circumference
double radius = center.distance(circum);
position = new Point(center.x - (int)radius, center.y - (int)radius);
circle = new Ellipse2D.Double(origin.x, origin.y, 2.*radius, 2.*radius);
bounds = new java.awt.Rectangle(position.x, position.y,
1 + (int)circle.width, 1 + (int)circle.height);
} // Display the circle
public void draw(Graphics2D g2D) {
draw(g2D, circle); // Draw the circle
} // Recreate this circle
public void modify(Point center, Point circum) {
double radius = center.distance(circum);
circle.width = circle.height = 2*radius;
position.x = center.x - (int)radius;
position.y = center.y - (int)radius;
bounds = new java.awt.Rectangle(position.x, position.y,
1 + (int)circle.width, 1 + (int)circle.height);
} private Ellipse2D.Double circle;
private final static long serialVersionUID = 1001L;
} // Nested class defining a curve
public static class Curve extends Element {
public Curve(Point start, Point next, Color color) {
super(start, color);
curve = new GeneralPath();
curve.moveTo(origin.x, origin.y); // Set current position as origin
curve.lineTo(next.x - position.x, next.y - position.y); // Add segment
bounds = new java.awt.Rectangle(
Math.min(start.x, next.x), Math.min(start.y, next.y),
Math.abs(next.x - start.x)+1, Math.abs(next.y - start.y)+1);
} // Add another segment
public void modify(Point start, Point next) {
curve.lineTo(next.x - position.x, next.y - position.y); // Add segment
bounds.add(new java.awt.Rectangle(next.x,next.y, 1, 1)); // Extend bounds
} // Display the curve
public void draw(Graphics2D g2D) {
draw(g2D, curve); // Draw the curve
} private GeneralPath curve;
private final static long serialVersionUID = 1001L;
} // Nested class defining a Text element
public static class Text extends Element {
public Text(String text, Point start, Color color, FontMetrics fm) {
super(start, color);
this.text = text;
this.font = fm.getFont();
maxAscent = fm.getMaxAscent();
bounds = new java.awt.Rectangle(position.x, position.y,
fm.stringWidth(text) + 4, maxAscent+ fm.getMaxDescent() + 4);
} public void draw(Graphics2D g2D) {
g2D.setPaint(highlighted ? HIGHLIGHT_COLOR : color);
Font oldFont = g2D.getFont(); // Save the old font
g2D.setFont(font); // Set the new font AffineTransform old = g2D.getTransform(); // Save the current transform
g2D.translate((double)position.x, (double)position.y); // Add translation transform to current
g2D.rotate(angle); // Rotate about position
// Reference point for drawString() is the baseline of the 1st character
g2D.drawString(text, origin.x + 2, maxAscent + 2);
g2D.setTransform(old); // Restore original transform
g2D.setFont(oldFont); // Restore the old font
} public void modify(Point start, Point last) {
// No code is required here, but you must supply a definition
} private Font font; // The font to be used
private int maxAscent; // Maximum ascent
private String text; // Text to be displayed
private final static long serialVersionUID = 1001L;
} // Abstract Element class methods
public abstract void draw(Graphics2D g2D);
public abstract void modify(Point start, Point last); // Element class fields
protected Point position; // Position of a shape
protected Color color; // Color of a shape
protected java.awt.Rectangle bounds; // Bounding rectangle
protected static final Point origin = new Point(); // Origin for elements
protected boolean highlighted = false; // Highlight flag
protected double angle = 0.0; // Element rotation
private final static long serialVersionUID = 1001L;
}

4、模型类:

 import java.io.Serializable;
import java.util.*; public class SketcherModel extends Observable implements Serializable, Iterable<Element> { //Remove an element from the sketch
public boolean remove(Element element) {
boolean removed = elements.remove(element);
if(removed) {
setChanged();
notifyObservers(element.getBounds());
}
return removed;
} //Add an element to the sketch
public void add(Element element) {
elements.add(element);
setChanged();
notifyObservers(element.getBounds());
} // Get iterator for sketch elements
public Iterator<Element> iterator() {
return elements.iterator();
} protected LinkedList<Element> elements = new LinkedList<>();
private final static long serialVersionUID = 1001L;
}

5、字体对话框类:

 // Class to define a dialog to choose a font
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import static Constants.SketcherConstants.*; @SuppressWarnings("serial")
class FontDialog extends JDialog
implements ActionListener, // For buttons etc.
ListSelectionListener, // For list box
ChangeListener { // For the spinner
// Constructor
public FontDialog(SketcherFrame window) {
// Call the base constructor to create a modal dialog
super(window, "Font Selection", true);
font = window.getFont(); // Get the current font // Create the dialog button panel
JPanel buttonPane = new JPanel(); // Create a panel to hold buttons // Create and add the buttons to the buttonPane
buttonPane.add(ok = createButton("OK")); // Add the OK button
buttonPane.add(cancel = createButton("Cancel")); // Add the Cancel button
getContentPane().add(buttonPane, BorderLayout.SOUTH); // Add pane // Code to create the data input panel
JPanel dataPane = new JPanel(); // Create the data entry panel
dataPane.setBorder(BorderFactory.createCompoundBorder( // Pane border
BorderFactory.createLineBorder(Color.BLACK),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
GridBagLayout gbLayout = new GridBagLayout(); // Create the layout
dataPane.setLayout(gbLayout); // Set the pane layout
GridBagConstraints constraints = new GridBagConstraints(); // Create the font choice and add it to the input panel
JLabel label = new JLabel("Choose a Font");
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridwidth = GridBagConstraints.REMAINDER;
gbLayout.setConstraints(label, constraints);
dataPane.add(label); // Code to set up font list choice component
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = e.getAvailableFontFamilyNames(); // Get font names fontList = new JList<>(fontNames); // Create list of font names
fontList.setValueIsAdjusting(true); // single event selection
fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fontList.setSelectedValue(font.getFontName(),true);
fontList.addListSelectionListener(this);
fontList.setToolTipText("Choose a font");
JScrollPane chooseFont = new JScrollPane(fontList); // Scrollable list
chooseFont.setMinimumSize(new Dimension(400,100));
chooseFont.setWheelScrollingEnabled(true); // Enable mouse wheel scroll // Panel to display font sample
JPanel display = new JPanel(true);
fontDisplay = new JLabel("Sample Size: x X y Y z Z");
fontDisplay.setFont(font);
fontDisplay.setPreferredSize(new Dimension(350,100));
display.add(fontDisplay); //Create a split pane with font choice at the top and font display at the bottom
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
true,
chooseFont,
display);
gbLayout.setConstraints(splitPane, constraints); // Split pane constraints
dataPane.add(splitPane); // Add to the data pane // Set up the size choice using a spinner
JPanel sizePane = new JPanel(true); // Pane for size choices
label = new JLabel("Choose point size: "); // Prompt for point size
sizePane.add(label); // Add the prompt chooseSize = new JSpinner(new SpinnerNumberModel(font.getSize(),
POINT_SIZE_MIN, POINT_SIZE_MAX, POINT_SIZE_STEP));
chooseSize.setValue(font.getSize()); // Set current font size
chooseSize.addChangeListener(this);
sizePane.add(chooseSize); // Add spinner to pane
gbLayout.setConstraints(sizePane, constraints); // Set pane constraints
dataPane.add(sizePane); // Add the pane // Set up style options using radio buttons
bold = new JRadioButton("Bold", (font.getStyle() & Font.BOLD) > 0);
italic = new JRadioButton("Italic", (font.getStyle() & Font.ITALIC) > 0);
bold.addItemListener(new StyleListener(Font.BOLD)); // Add button listeners
italic.addItemListener(new StyleListener(Font.ITALIC));
JPanel stylePane = new JPanel(true); // Create style pane
stylePane.add(bold); // Add buttons
stylePane.add(italic); // to style pane...
gbLayout.setConstraints(stylePane, constraints); // Set pane constraints
dataPane.add(stylePane); // Add the pane getContentPane().add(dataPane, BorderLayout.CENTER);
pack();
setVisible(false);
} // Create a dialog button
JButton createButton(String label) {
JButton button = new JButton(label); // Create the button
button.setPreferredSize(new Dimension(80,20)); // Set the size
button.addActionListener(this); // Listener is the dialog
return button; // Return the button
} // Handler for button events
public void actionPerformed(ActionEvent e) {
if(e.getSource()== ok) { // If it's the OK button
((SketcherFrame)getOwner()).setFont(font); // ...set selected font
} else {
font = ((SketcherFrame)getOwner()).getFont(); // Restore the current font
fontDisplay.setFont(font);
chooseSize.setValue(font.getSize()); // Restore the point size
fontList.setSelectedValue(font.getName(),true);
int style = font.getStyle();
bold.setSelected((style & Font.BOLD) > 0); // Restore the
italic.setSelected((style & Font.ITALIC) > 0); // style options
}
// Now hide the dialog - for ok or cancel
setVisible(false);
} // List selection listener method
public void valueChanged(ListSelectionEvent e) {
if(!e.getValueIsAdjusting()) {
font = new Font(fontList.getSelectedValue(), font.getStyle(), font.getSize());
fontDisplay.setFont(font);
fontDisplay.repaint();
}
} // Handle spinner state change events
public void stateChanged(ChangeEvent e) {
int fontSize = ((Number)(((JSpinner)e.getSource()).getValue())).intValue();
font = font.deriveFont((float)fontSize);
fontDisplay.setFont(font);
fontDisplay.repaint();
} // Iner class defining listeners for radio buttons
class StyleListener implements ItemListener {
public StyleListener(int style) {
this.style = style;
} // Event handler for font style changes
public void itemStateChanged(ItemEvent e) {
int fontStyle = font.getStyle();
if(e.getStateChange()==ItemEvent.SELECTED) { // If style was selected
fontStyle |= style; // turn it on in the font style
} else {
fontStyle &= ~style; // otherwise turn it off
}
font = font.deriveFont(fontStyle); // Get a new font
fontDisplay.setFont(font); // Change the label font
fontDisplay.repaint(); // repaint
}
private int style; // Style for this listener
} private JList<String> fontList; // Font list
private JButton ok; // OK button
private JButton cancel; // Cancel button
private JRadioButton bold; // Bold style button
private JRadioButton italic; // Italic style button
private Font font; // Currently selected font
private JSpinner chooseSize; // Font size options
private JLabel fontDisplay; // Font sample
}

6、状态栏类:

 // Class defining a status bar
import javax.swing.*;
import java.awt.*;
import javax.swing.border.BevelBorder;
import static Constants.SketcherConstants.*; @SuppressWarnings("serial")
class StatusBar extends JPanel {
// Constructor
public StatusBar() {
setLayout(new FlowLayout(FlowLayout.LEFT, 10, 3));
setBackground(Color.LIGHT_GRAY);
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
setColorPane(DEFAULT_ELEMENT_COLOR);
setTypePane(DEFAULT_ELEMENT_TYPE);
add(colorPane); // Add color pane to status bar
add(typePane); // Add type pane to status bar
} // Set color pane contents
public void setColorPane(Color color) {
String text = null; // Text for the color pane
Icon icon = null; // Icon to be displayed
if(color.equals(Color.RED)) {
text = "RED";
icon = RED16;
} else if(color.equals(Color.YELLOW)) {
text = "YELLOW";
icon = YELLOW16;
} else if(color.equals(Color.GREEN)) {
text = "GREEN";
icon = GREEN16;
} else if(color.equals(Color.BLUE)) {
text = "BLUE";
icon = BLUE16;
} else {
text = "CUSTOM";
icon = CUSTOM16;
}
colorPane.setIcon(icon);
colorPane.setText(text); // Set the pane text
} // Set type pane label
public void setTypePane(int elementType) {
String text = null; // Text for the type pane
switch(elementType) {
case LINE:
text = "LINE";
break;
case RECTANGLE:
text = "RECTANGLE";
break;
case CIRCLE:
text = "CIRCLE";
break;
case CURVE:
text = "CURVE";
break;
case TEXT:
text = "TEXT";
break;
default:
assert false;
}
typePane.setText(text); // Set the pane text
} // Panes in the status bar
private StatusPane colorPane = new StatusPane("BLUE", BLUE16);;
private StatusPane typePane = new StatusPane("LINE"); // Class defining a status bar pane
class StatusPane extends JLabel {
// Constructor - text only
public StatusPane(String text) {
super(text, LEFT);
setupPane();
} // Constructor - text with an icon
public StatusPane(String text, Icon icon) {
super(text, icon, LEFT);
setupPane();
} // Helper method for use by constructors
private void setupPane() {
setBackground(Color.LIGHT_GRAY); // Set background color
setForeground(Color.BLACK); // Set foreground color
setFont(paneFont); // Set the fixed font
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createBevelBorder(BevelBorder.LOWERED), // Outside border
BorderFactory.createEmptyBorder(0,5,0,3))); // Inside border
setPreferredSize(new Dimension(80,20));
} // Font for pane text
private Font paneFont = new Font("Serif", Font.PLAIN, 10);
}
}

7、视图类:

 import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.MouseInputAdapter;
import static Constants.SketcherConstants.*;
import java.awt.geom.Line2D; @SuppressWarnings("serial")
public class SketcherView extends JComponent implements Observer {
public SketcherView(Sketcher theApp) {
this.theApp = theApp;
MouseHandler handler = new MouseHandler(); // create the mouse listener
addMouseListener(handler); // Listen for button events
addMouseMotionListener(handler); // Listen for motion events // Add the pop-up menu items
JMenuItem moveItem = elementPopup.add(new JMenuItem("Move"));
JMenuItem deleteItem = elementPopup.add(new JMenuItem("Delete"));
JMenuItem rotateItem = elementPopup.add(new JMenuItem("Rotate"));
JMenuItem sendToBackItem = elementPopup.add(new JMenuItem("Send-to-back")); // Create the menu item listeners
moveItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
mode = MOVE;
selectedElement = highlightElement;
}
});
deleteItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
deleteElement();
}
});
rotateItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
mode = ROTATE;
selectedElement = highlightElement;
}
});
sendToBackItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
sendToBack(); // Handle the send-to-back event
}
});
} // Send-to Back operation
private void sendToBack() {
if(highlightElement != null) {
SketcherModel sketch = theApp.getModel();
if(sketch.remove(highlightElement)) {
sketch.add(highlightElement);
} else {
JOptionPane.showMessageDialog(
SketcherView.this,"Element not found to remove.",
"Remove Element from Sketch", JOptionPane.ERROR_MESSAGE);
}
}
} // Delete element operation
private void deleteElement() {
if(highlightElement != null) {
if(!theApp.getModel().remove(highlightElement)) {
JOptionPane.showMessageDialog(
SketcherView.this,"Element not found to remove.",
"Remove Element from Sketch", JOptionPane.ERROR_MESSAGE);
}
highlightElement = null;
}
} // Method called by Observable object when it changes
public void update(Observable o, Object rectangle) {
if(rectangle != null) {
repaint((java.awt.Rectangle)rectangle);
} else {
repaint();
}
} // Method to draw on the view
@Override
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D)g; // Get a 2D device context
for(Element element: theApp.getModel()) { // For each element in the model
element.draw(g2D); // ...draw the element
}
} class MouseHandler extends MouseInputAdapter {
@Override
public void mousePressed(MouseEvent e) {
start = e.getPoint(); // Save the cursor position in start
buttonState = e.getButton(); // Record which button was pressed if(showContextMenu(e)) {
start = null;
buttonState = MouseEvent.NOBUTTON;
return;
} if(theApp.getWindow().getElementType() == TEXT && mode == NORMAL) return; // Initialize rotation angles when mode is ROTATE
if(mode == ROTATE && selectedElement != null) {
oldAngle = selectedElement.getRotation();
angle = 0.0;
} if(buttonState == MouseEvent.BUTTON1 && mode == NORMAL) {
g2D = (Graphics2D)getGraphics(); // Get graphics context
g2D.setXORMode(getBackground()); // Set XOR mode
}
} // Show the context menu when an element is highlighted
private boolean showContextMenu(MouseEvent e) {
if(e.isPopupTrigger()){
if(last != null) { // If mouse was dragged
start = last; // show popup at last cursor position
}
if(highlightElement == null) { // If there is no highlighted element
// Show the popup menu from the app window
theApp.getWindow().getPopup().show(SketcherView.this, start.x, start.y);
} else { // Otherwise...
// Show the element operations context menu
elementPopup.show(SketcherView.this, start.x, start.y);
}
return true;
}
return false;
} @Override
public void mouseDragged(MouseEvent e) {
last = e.getPoint(); // Save cursor position
if(theApp.getWindow().getElementType() == TEXT && mode == NORMAL) return; // Select operation based on sketching mode
switch(mode){
case NORMAL:
// Creating an element
if(buttonState == MouseEvent.BUTTON1) {
if(tempElement == null) { // Is there an element?
tempElement = Element.createElement( // No, so create one
theApp.getWindow().getElementType(),
theApp.getWindow().getElementColor(),
start, last);
} else {
tempElement.draw(g2D); // Yes draw to erase it
tempElement.modify(start, last); // Now modify it
}
tempElement.draw(g2D); // and draw it
}
break;
case MOVE:
// Moving an element
if(buttonState == MouseEvent.BUTTON1 && selectedElement != null) {
selectedElement.move(last.x-start.x, last.y-start.y); // Move it
repaint();
start = last; // Make start current point
}
break;
case ROTATE:
// Rotating an element
if(buttonState == MouseEvent.BUTTON1 && selectedElement != null) {
angle += getAngle(selectedElement.getPosition(), start, last);
if(angle != 0.0) { // If there is rotation
selectedElement.setRotation(oldAngle + angle); // Rotate the element
repaint(); // Repaint the view
start = last; // last is start next time
}
}
break;
}
} // Helper method for calculating the rotation angle
double getAngle(Point position, Point start, Point last) {
// Get perpendicular distance from last to line from position to start
double perp = Line2D.ptLineDist(position.x, position.y,
last.x, last.y, start.x, start.y); // Get the distance from position to start
double hypotenuse = position.distance(start); if(perp < 1.0 || hypotenuse < 1.0) return 0.0; // Ensure sensible values // Angle is the arc sine of perp/hypotenuse. Clockwise is positive angle
return -Line2D.relativeCCW(position.x, position.y, start.x, start.y,
last.x, last.y)*Math.asin(perp/hypotenuse);
} @Override
public void mouseReleased(MouseEvent e) {
if(mode == MOVE || mode == ROTATE) {
selectedElement = null;
start = last = null;
mode = NORMAL;
return;
} if(showContextMenu(e)) {
start = last = null;
return;
} // Check for TEXT being the element type
if(theApp.getWindow().getElementType() == TEXT && mode == NORMAL) {
if(last != null) {
start = last = null;
}
return;
} if(e.getButton() == MouseEvent.BUTTON1) {
buttonState = MouseEvent.NOBUTTON; // Reset the button state if(tempElement != null) { // If there is an element...
theApp.getModel().add(tempElement); // ...add it to the model...
tempElement = null; // ...and reset the field
}
if(g2D != null) { // If there抯 a graphics context
g2D.dispose(); // ...release the resource...
g2D = null; // ...and reset field to null
}
start = last = null; // Remove any points
mode = NORMAL; // Always normal after mouse released
}
} @Override
public void mouseClicked(MouseEvent e) {
// Only if it's TEXT and button 1 was clicked
if(theApp.getWindow().getElementType() == TEXT &&
buttonState == MouseEvent.BUTTON1) {
String text = JOptionPane.showInputDialog(
theApp.getWindow(),"Enter Input:",
"Create Text Element", JOptionPane.PLAIN_MESSAGE); if(text != null && !text.isEmpty()) { // Only if text was entered
g2D = (Graphics2D)getGraphics();
tempElement = new Element.Text(text,
start,
theApp.getWindow().getElementColor(),
g2D.getFontMetrics(theApp.getWindow().getFont()));
g2D.dispose();
g2D = null;
if(tempElement != null) {
theApp.getModel().add(tempElement);
}
}
tempElement = null; // Reset for next element creation
start = null; // Reset for next element
}
} // Handle mouse move events
@Override
public void mouseMoved(MouseEvent e) {
Point cursor = e.getPoint(); // Get current cursor position for(Element element : theApp.getModel()) { // Go through the list...
if(element.getBounds().contains(cursor)) { // ....under the cursor
if(element==highlightElement) { // If it's already highlighted
return; // we are done
} // Un-highlight any existing highlighted element
if(highlightElement!= null) { // If an element is highlighted
highlightElement.setHighlighted(false); // un-highlight it and
repaint(highlightElement.getBounds()); //... redraw it
} element.setHighlighted(true); // Set highlight for new element
highlightElement = element; // Store new highlighted element
repaint(highlightElement.getBounds());
return;
}
} // Here there is no element under the cursor so...
if(highlightElement!=null) { // If an element is highlighted...
highlightElement.setHighlighted(false); // ...turn off highlighting...
repaint(highlightElement.getBounds()); // ... and redraw the element
highlightElement = null; // No element highlighted
}
} @Override
public void mouseEntered(MouseEvent e) {
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
} @Override
public void mouseExited(MouseEvent e) {
setCursor(Cursor.getDefaultCursor());
} private Point start; // Stores cursor position on press
private Point last; // Stores cursor position on drag
private Element tempElement = null; // Stores a temporary element
private int buttonState = MouseEvent.NOBUTTON; // Records button state
private Graphics2D g2D = null; // Temporary graphics context
} private Sketcher theApp; // The application object
private Element highlightElement; // Highlighted element
private Element selectedElement; // Element for move or rotate operation
private double oldAngle = 0.0; // Initial element rotation
private double angle = 0.0; // Additional rotation // Element operations context menu
private JPopupMenu elementPopup = new JPopupMenu("Element Operations"); private String mode = NORMAL; // Sketching mode
}

8、Sketcher类:

 // Sketching application
import javax.swing.*;
import java.awt.*;
import java.awt.event.*; public class Sketcher {
public static void main(String[] args) {
theApp = new Sketcher(); // Create the application object
SwingUtilities.invokeLater(new Runnable() {
public void run() {
theApp.createGUI(); // Call GUI creator
}
});
} // Method to create the application GUI
private void createGUI() {
window = new SketcherFrame("Sketcher", this); // Create the app window
Toolkit theKit = window.getToolkit(); // Get the window toolkit
Dimension wndSize = theKit.getScreenSize(); // Get screen size // Set the position to screen center & size to half screen size
window.setSize(wndSize.width/2, wndSize.height/2); // Set window size
window.setLocationRelativeTo(null); // Center window window.addWindowListener(new WindowHandler()); // Add window listener sketch = new SketcherModel(); // Create the model
view = new SketcherView(this); // Create the view
sketch.addObserver(view); // Register view with the model
window.getContentPane().add(view, BorderLayout.CENTER);
window.setVisible(true);
} // Return a reference to the application window
public SketcherFrame getWindow() {
return window;
} // Return a reference to the model
public SketcherModel getModel() {
return sketch;
} // Return a reference to the view
public SketcherView getView() {
return view;
} // Handler class for window events
class WindowHandler extends WindowAdapter {
// Handler for window closing event
@Override
public void windowClosing(WindowEvent e) {
// Code to be added here...
}
} private SketcherModel sketch; // The data model for the sketch
private SketcherView view; // The view of the sketch
private SketcherFrame window; // The application window
private static Sketcher theApp; // The application object
}

Java基础之扩展GUI——高亮元素、上下文菜单、移动旋转元素、自定义颜色(Sketcher 10)的更多相关文章

  1. Java基础之扩展GUI——使用对话框创建文本元素(Sketcher 4 creating text elements)

    控制台程序. 为了与Sketcher中的其他元素类型保持一致,需要为Elements菜单添加Text菜单项和工具栏按钮.还需要定义用来表示文本元素的类Element.Text. 1.修改Sketche ...

  2. Java基础之扩展GUI——使用字体对话框(Sketcher 5 displaying a font dialog)

    控制台程序. 为了可以选择系统支持的字体,我们定义了一个FontDialog类: // Class to define a dialog to choose a font import java.aw ...

  3. Java基础之扩展GUI——显示About对话框(Sketcher 2 displaying an About dialog)

    控制台程序. 最简单的对话框仅仅显示一些信息.为了说明这一点,可以为Sketcher添加Help菜单项和About菜单项,之后再显示About对话框来提供有关应用程序的信息. 要新建的对话框类从JDi ...

  4. Java基础之扩展GUI——添加状态栏(Sketcher 1 with a status bar)

    控制台程序. 为了显示各个应用程序参数的状态,并且将各个参数显示在各自的面板中,在应用程序窗口的底部添加状态栏是常见且非常方便的方式. 定义状态栏时没有Swing类可用,所以必须自己建立StatusB ...

  5. java基础学习总结——GUI编程(二)

    一.事件监听

  6. java基础学习总结——GUI编程(一)

    一.AWT介绍

  7. java基础学习总结——GUI编程(二) 未学习

    一.事件监听

  8. java基础学习总结——GUI编程(一) 还未仔细阅读

    一.AWT介绍

  9. 【Java基础总结】GUI

    GUI(Graphical User Interface),图形用户接口 CLI(Command Line User Interface),命令行用户接口 1. 容器 Container GUI主要位 ...

随机推荐

  1. Code[VS]1690 开关灯 题解

    Code[VS]1690 开关灯 题解     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description:     YYX家门前 ...

  2. 【BZOJ】1110: [POI2007]砝码Odw

    题意 给定\(n\)个砝码和\(m(1 \le n, m \le 100000)\)个背包\((1 \le n_i, m_i \le 1000000000)\),保证对于任意两个砝码都有一个是另一个的 ...

  3. FLEX监视浏览器关闭事件

    在最近开发的一个FLEX项目中对于浏览器关闭时,需要做一些清理工作,该清理工作在正常情况下保证能运行就行了,要求不是太高. 因此在网上找了一些方法,经过实际测试确实可行,记录下来备查. 该方法可以完全 ...

  4. 实现Map-side Join和Reduce-side Join(转)

    在大数据处理场景中,多表Join是非常常见的一类运算.为了便于求解,通常会将多表join问题转为多个两表连接问题.两表Join的实现算法非常多,一般我们会根据两表的数据特点选取不同的join算法,其中 ...

  5. maven的简单说明

    groupId: 项目组ID,项目坐标的核心元素. version: 项目版本,项目坐标的核心元素. description: 项目的描述信息. organization: 项目的组织信息.incep ...

  6. android-Activity(四大组件之一)

    一.Activity理解 1.定义: 直译为活动,是Android定义四大应用组件之一,也是最重要的用的最多的: 用来提供一个能让用户操作并与之交互的界面 一个应用有多个界面也就是包含多个Activi ...

  7. .net Sql语句批量插入数据库数据

    #region 使用SqlBulkCopy public static bool ExecuteTransactionScopeInsert(DataTable dt, int batchSize) ...

  8. 笔记本(WIN7|XP)发射wifi信号 当无线路由使用

    Windows7系统 第一步:是你的电脑上要有两个网卡一个有线一个无线(笔记本应该都有)台式机可以考虑买个USB无线网卡(50左右) 第二步:win+R  CMD  输入(只输入红色部分) netsh ...

  9. linux应用于发展(下)

    X windows的特点 1.独立于操作系统. 2.网络特性. 3.源码开源. Unix图形环境主要还是CDE linux主要还是在网络应用和嵌入式上使用较多. 娱乐办公什么的去windows吧. 网 ...

  10. C++STL -- vector 使用

    vector是一种顺序容器. vector常用API: 现在一个个分析: 1. assign 这是一种赋值方法,但是会覆盖原来容器内的值. void assign( size_type num, co ...