import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;import static java.awt.BorderLayout.*;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;/**
 * Description:
 * <br/>Copyright (C), 2005-2008, Yeeku.H.Lee
 * <br/>This program is protected by copyright laws.
 * <br/>Program Name:
 * <br/>Date:
 * @author  Yeeku.H.Lee [email protected]
 * @version  1.0
 */
public class HandDraw
{
//画图区的宽度 
private final static int AREA_WIDTH = 500;
//画图区的高度
private final static int AREA_HEIGHT = 400;
//下面的preX、preY保存了上一次鼠标拖动事件的鼠标座标
private int preX = -1;
private int preY = -1;
//定义一个右键菜单用于设置画笔颜色
PopupMenu pop = new PopupMenu();
MenuItem redItem = new MenuItem("红色");
MenuItem greenItem = new MenuItem("绿色");
MenuItem blueItem = new MenuItem("蓝色");
//定义一个BufferedImage对象
static BufferedImage image = new BufferedImage(AREA_WIDTH , AREA_HEIGHT , 
BufferedImage.TYPE_INT_RGB);
//获取image对象的Graphics
Graphics g = image.getGraphics();
private Frame f = new Frame("简单手绘程序");
private DrawCanvas drawArea = new DrawCanvas();
//用于保存需要绘制什么图形的字符串属性
private String shape = "";
//用于保存画笔颜色
private Color foreColor = new Color(255, 0 ,0);

// 画笔样式的监听事件
private ButtonStrokeAction buttonStrokeAction = null;
private Label drawWidth = null;

// 画笔端点的装饰
private Label drawCap = null;

public void init()
{   


// 画笔颜色选择器
Panel paneStroke = new Panel(new GridLayout(1, 13));

// 控制画笔样式
buttonStrokeAction = new ButtonStrokeAction();
Button [] buttonStroke = new Button[11];
buttonStroke[0] = new Button("1");
buttonStroke[1] = new Button("3");
buttonStroke[2] = new Button("5");
buttonStroke[3] = new Button("7");
buttonStroke[4] = new Button("9");
buttonStroke[5] = new Button("11");
buttonStroke[6] = new Button("13");
buttonStroke[7] = new Button("15");
buttonStroke[8] = new Button("17");
buttonStroke[9] = new Button("■");
buttonStroke[10] = new Button("●");
drawWidth = new Label("3", Label.CENTER);
drawCap = new Label("●", Label.CENTER);
drawWidth.setBackground(Color.lightGray);
drawCap.setBackground(Color.lightGray);
paneStroke.add(drawWidth);
for(int i = 0; i < buttonStroke.length; i++){
paneStroke.add(buttonStroke[i]);

buttonStroke[i].addActionListener(buttonStrokeAction);
if(i <= 8){
buttonStroke[i].setName("width");
}else{
buttonStroke[i].setName("cap");
}
if(i == 8){
paneStroke.add(drawCap);
}
}





//定义右键菜单的事件监听器。
ActionListener menuListener = new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (e.getActionCommand().equals("绿色"))
{
foreColor = new Color(0 , 255 , 0);
}
if (e.getActionCommand().equals("红色"))
{
foreColor = new Color(255 , 0 , 0);
}
if (e.getActionCommand().equals("蓝色"))
{
foreColor = new Color(0 , 0 , 255);
}
}
};
//为三个菜单添加事件监听器
redItem.addActionListener(menuListener);
greenItem.addActionListener(menuListener);
blueItem.addActionListener(menuListener);
//将菜单项组合成右键菜单
pop.add(redItem);
pop.add(greenItem);
pop.add(blueItem);
//将右键菜单添加到drawArea对象中
drawArea.add(pop);
//将image对象的背景色填充成白色
g.fillRect(0 , 0 ,AREA_WIDTH , AREA_HEIGHT);
drawArea.setPreferredSize(new Dimension(AREA_WIDTH , AREA_HEIGHT));
//监听鼠标移动动作
drawArea.addMouseMotionListener(new MouseMotionAdapter()
{
//实现按下鼠标键并拖动的事件处理器
public void mouseDragged(MouseEvent e)
{
//如果preX和preY大于0
if (preX > 0 && preY > 0)
{
//设置当前颜色
g.setColor(foreColor);
//绘制从上一次鼠标拖动事件点到本次鼠标拖动事件点的线段
g.drawLine(preX , preY , e.getX() , e.getY());
}
//将当前鼠标事件点的X、Y座标保存起来
preX = e.getX();
preY = e.getY();
//重绘drawArea对象
drawArea.repaint();
}
});
//监听鼠标事件
drawArea.addMouseListener(new MouseAdapter()
{
//实现鼠标松开的事件处理器
public void mouseReleased(MouseEvent e)
{
//弹出右键菜单
if (e.isPopupTrigger())
{
pop.show(drawArea , e.getX() , e.getY());
}
//松开鼠标键时,把上一次鼠标拖动事件的X、Y座标设为-1。
preX = -1;
preY = -1;
}
});

class MyListener extends WindowAdapter
{
public void windowClosing(WindowEvent e) 
{

System.exit(0);
}
}
f.addWindowListener(new MyListener());
f.add(paneStroke, NORTH);
f.add(drawArea);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) 
{
new HandDraw().init();
}
static class DrawCanvas extends Canvas 
{private static BasicStroke stroke = null;
//重写Canvas的paint方法,实现绘画
public void paint(Graphics g)
{
//将image绘制到该组件上
g.drawImage(image , 0 , 0 , null);
}



public BasicStroke getStroke() {
return getStroke();
} /**
 * @param stroke 要设置的 stroke
 */
public void setStroke(BasicStroke stroke) {
this.stroke = stroke;
}


/**
 * 设置画笔粗细
 * @param width
 */
public static void setStroke(float width) {
stroke = new BasicStroke(width, stroke.getEndCap(), stroke.getLineJoin());
}

/**
 * 设置画笔端点的装饰
 * @param cap 参考 java.awt.BasicStroke 类静态字段
 */
public static void setStroke(int cap) {
stroke = new BasicStroke(stroke.getLineWidth(), cap, stroke.getLineJoin());
}



}



class ButtonStrokeAction implements ActionListener { public void actionPerformed(ActionEvent e) {
Button button_temp = (Button) e.getSource();
String name = button_temp.getName();
if(name.equalsIgnoreCase("width")){
drawWidth.setText(button_temp.getLabel());
DrawCanvas.setStroke(Float.parseFloat(button_temp.getLabel()));
}else if(name.equalsIgnoreCase("cap")){
drawCap.setText(button_temp.getLabel());
if(button_temp.getLabel().equals("■")){
DrawCanvas.setStroke(BasicStroke.CAP_SQUARE);
}else if(button_temp.getLabel().equals("●")){
DrawCanvas.setStroke(BasicStroke.CAP_ROUND);
}
}
}

}}
运行时候随便点任一个按钮都提示
提示Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at HandDraw$DrawCanvas.setStroke(HandDraw.java:233)
at HandDraw$ButtonStrokeAction.actionPerformed(HandDraw.java:257)
at java.awt.Button.processActionEvent(Unknown Source)
at java.awt.Button.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

解决方案 »

  1.   

    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.BufferedImage;import static java.awt.BorderLayout.*;
    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Button;
    import java.awt.Color;
    import java.awt.Cursor;
    import java.awt.Dimension;
    import java.awt.Frame;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.GridLayout;
    import java.awt.Label;
    import java.awt.Panel;
    import java.awt.RenderingHints;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.image.BufferedImage;/**
     * Description: <br/>
     * Copyright (C), 2005-2008, Yeeku.H.Lee <br/>
     * This program is protected by copyright laws. <br/>
     * Program Name: <br/>
     * Date:
     * 
     * @author Yeeku.H.Lee [email protected]
     * @version 1.0
     */
    public class HandDraw {
    // 画图区的宽度
    private final static int AREA_WIDTH = 500;
    // 画图区的高度
    private final static int AREA_HEIGHT = 400;
    // 下面的preX、preY保存了上一次鼠标拖动事件的鼠标座标
    private int preX = -1;
    private int preY = -1;
    // 定义一个右键菜单用于设置画笔颜色
    PopupMenu pop = new PopupMenu();
    MenuItem redItem = new MenuItem("红色");
    MenuItem greenItem = new MenuItem("绿色");
    MenuItem blueItem = new MenuItem("蓝色");
    // 定义一个BufferedImage对象
    static BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT,
    BufferedImage.TYPE_INT_RGB);
    // 获取image对象的Graphics
    Graphics g = image.getGraphics();
    private Frame f = new Frame("简单手绘程序");
    private DrawCanvas drawArea = new DrawCanvas();
    // 用于保存需要绘制什么图形的字符串属性
    private String shape = "";
    // 用于保存画笔颜色
    private Color foreColor = new Color(255, 0, 0); // 画笔样式的监听事件
    private ButtonStrokeAction buttonStrokeAction = null;
    private Label drawWidth = null; // 画笔端点的装饰
    private Label drawCap = null; public void init() { // 画笔颜色选择器
    Panel paneStroke = new Panel(new GridLayout(1, 13)); // 控制画笔样式
    buttonStrokeAction = new ButtonStrokeAction();
    Button[] buttonStroke = new Button[11];
    buttonStroke[0] = new Button("1");
    buttonStroke[1] = new Button("3");
    buttonStroke[2] = new Button("5");
    buttonStroke[3] = new Button("7");
    buttonStroke[4] = new Button("9");
    buttonStroke[5] = new Button("11");
    buttonStroke[6] = new Button("13");
    buttonStroke[7] = new Button("15");
    buttonStroke[8] = new Button("17");
    buttonStroke[9] = new Button("■");
    buttonStroke[10] = new Button("●");
    drawWidth = new Label("3", Label.CENTER);
    drawCap = new Label("●", Label.CENTER);
    drawWidth.setBackground(Color.lightGray);
    drawCap.setBackground(Color.lightGray);
    paneStroke.add(drawWidth);
    for (int i = 0; i < buttonStroke.length; i++) {
    paneStroke.add(buttonStroke[i]); buttonStroke[i].addActionListener(buttonStrokeAction);
    if (i <= 8) {
    buttonStroke[i].setName("width");
    } else {
    buttonStroke[i].setName("cap");
    }
    if (i == 8) {
    paneStroke.add(drawCap);
    }
    } // 定义右键菜单的事件监听器。
    ActionListener menuListener = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
    if (e.getActionCommand().equals("绿色")) {
    foreColor = new Color(0, 255, 0);
    }
    if (e.getActionCommand().equals("红色")) {
    foreColor = new Color(255, 0, 0);
    }
    if (e.getActionCommand().equals("蓝色")) {
    foreColor = new Color(0, 0, 255);
    }
    }
    };
    // 为三个菜单添加事件监听器
    redItem.addActionListener(menuListener);
    greenItem.addActionListener(menuListener);
    blueItem.addActionListener(menuListener);
    // 将菜单项组合成右键菜单
    pop.add(redItem);
    pop.add(greenItem);
    pop.add(blueItem);
    // 将右键菜单添加到drawArea对象中
    drawArea.add(pop);
    // 将image对象的背景色填充成白色
    g.fillRect(0, 0, AREA_WIDTH, AREA_HEIGHT);
    drawArea.setPreferredSize(new Dimension(AREA_WIDTH, AREA_HEIGHT));
    // 监听鼠标移动动作
    drawArea.addMouseMotionListener(new MouseMotionAdapter() {
    // 实现按下鼠标键并拖动的事件处理器
    public void mouseDragged(MouseEvent e) {
    // 如果preX和preY大于0
    if (preX > 0 && preY > 0) {
    // 设置当前颜色
    g.setColor(foreColor);
    // 绘制从上一次鼠标拖动事件点到本次鼠标拖动事件点的线段
    g.drawLine(preX, preY, e.getX(), e.getY());
    }
    // 将当前鼠标事件点的X、Y座标保存起来
    preX = e.getX();
    preY = e.getY();
    // 重绘drawArea对象
    drawArea.repaint();
    }
    });
    // 监听鼠标事件
    drawArea.addMouseListener(new MouseAdapter() {
    // 实现鼠标松开的事件处理器
    public void mouseReleased(MouseEvent e) {
    // 弹出右键菜单
    if (e.isPopupTrigger()) {
    pop.show(drawArea, e.getX(), e.getY());
    }
    // 松开鼠标键时,把上一次鼠标拖动事件的X、Y座标设为-1。
    preX = -1;
    preY = -1;
    }
    }); class MyListener extends WindowAdapter {
    public void windowClosing(WindowEvent e) { System.exit(0);
    }
    }
    f.addWindowListener(new MyListener());
    f.add(paneStroke, NORTH);
    f.add(drawArea);
    f.pack();
    f.setVisible(true);
    } public static void main(String[] args) {
    new HandDraw().init();
    } static class DrawCanvas extends Canvas {
    private static BasicStroke stroke = null; // 重写Canvas的paint方法,实现绘画
    public void paint(Graphics g) {
    // 将image绘制到该组件上
    g.drawImage(image, 0, 0, null);
    } public BasicStroke getStroke() {
    return getStroke();
    } /**
     * @param stroke
     *            要设置的 stroke
     */
    public void setStroke(BasicStroke stroke) {
    this.stroke = stroke;
    } /**
     * 设置画笔粗细
     * 
     * @param width
     */
    public static void setStroke(float width) {
    stroke = new BasicStroke(width);
    } /**
     * 设置画笔端点的装饰
     * 
     * @param cap
     *            参考 java.awt.BasicStroke 类静态字段
     */
    public static void setStroke(int cap) {
    stroke = new BasicStroke(stroke.getLineWidth(), cap,
    stroke.getLineJoin());
    } } class ButtonStrokeAction implements ActionListener { public void actionPerformed(ActionEvent e) {
    Button button_temp = (Button) e.getSource();
    String name = button_temp.getName();
    if (name.equalsIgnoreCase("width")) {
    drawWidth.setText(button_temp.getLabel());
    DrawCanvas.setStroke(Float.parseFloat(button_temp.getLabel()));
    } else if (name.equalsIgnoreCase("cap")) {
    drawCap.setText(button_temp.getLabel());
    if (button_temp.getLabel().equals("■")) {
    DrawCanvas.setStroke(BasicStroke.CAP_SQUARE);
    } else if (button_temp.getLabel().equals("●")) {
    DrawCanvas.setStroke(BasicStroke.CAP_ROUND);
    }
    }
    } }}
      

  2.   

    为什么要改stroke = new BasicStroke(width);这个
    改成这个后,点击按钮,线条不会发生改变的。。为什么呢