# 1
I have seen this problem myself. See the solution I implemented in PaintArea. It actually works pretty well
You are welcome to use and modify this class, but please don't change the package or take credit for it as your own work
ps as far as the MathUtils class you might be able to find it searching this site with tjacobs01 and the class name. If not, try the same search on google. Or you could just reimplement them. None of them are that complicated (just angle which uses Math.atan2 and distance - the square root of the squares)
PaintArea.java
===========
/*
* Created on Jun 15, 2005 by @author Tom Jacobs
*
*/
package tjacobs.ui;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import tjacobs.MathUtils;
/**
* PaintArea is a component that you can draw in similar to but
* much simpler than the windows paint program.
*/
public class PaintArea extends JComponent {
BufferedImage mImg; //= new BufferedImage();
int mBrushSize = 1;
private boolean mSizeChanged = false;
private Color mColor1, mColor2;
static class PaintIcon extends ImageIcon {
int mSize;
public PaintIcon(Image im, int size) {
super(im);
mSize = size;
}
}
public PaintArea() {
super();
setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
addComponentListener(new CListener());
MListener ml = new MListener();
addMouseListener(ml);
addMouseMotionListener(ml);
setBackground(Color.WHITE);
setForeground(Color.BLACK);
}
public void paintComponent(Graphics g) {
if (mSizeChanged) {
handleResize();
}
//g.drawImage(mImg, mImg.getWidth(), mImg.getHeight(), null);
g.drawImage(mImg, 0, 0, null);
//super.paintComponent(g);
//System.out.println("Image = " + mImg);
//System.out.println("Size: " + mImg.getWidth() + "," + mImg.getHeight());
}
public void setBackground(Color c) {
super.setBackground(c);
if (mImg != null) {
Graphics g = mImg.getGraphics();
g.setColor(c);
g.fillRect(0, 0, mImg.getWidth(), mImg.getHeight());
g.dispose();
}
}
public void setColor1(Color c) {
mColor1 = c;
}
public void setColor2(Color c) {
mColor2 = c;
}
public Color getColor1() {
return mColor1;
}
public Color getColor2() {
return mColor2;
}
class ToolBar extends JToolBar {
ToolBar() {
final ColorButton fore = new ColorButton();
fore.setToolTipText("Foreground Color");
final ColorButton back = new ColorButton();
back.setToolTipText("Background Color");
JComboBox brushSize = new JComboBox();
//super.createImage(1, 1).;
FontMetrics fm = new FontMetrics(getFont()) {};
int ht = fm.getHeight();
int useheight = fm.getHeight() % 2 == 0 ? fm.getHeight() + 1 : fm.getHeight();
final BufferedImage im1 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
Graphics g = im1.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2, useheight / 2, 1, 1);
g.dispose();
//im1.setRGB(useheight / 2 + 1, useheight / 2 + 1, 0xFFFFFF);
final BufferedImage im2 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
g = im2.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2 - 1, useheight / 2 - 1, 3, 3);
g.dispose();
//im2.setRGB(useheight / 2 - 1, useheight / 2 - 1, 3, 3, new int[] {0, 0xFFFFFF, 0,
//0xFFFFFF, 0xFFFFFFF, 0xFFFFFF,
//0, 0xFFFFFF, 0}, 0, 1);
final BufferedImage im3 = new BufferedImage(useheight, useheight, BufferedImage.TYPE_INT_RGB);
g = im3.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, useheight, useheight);
g.setColor(Color.BLACK);
g.fillOval(useheight / 2 - 2, useheight / 2 - 2, 5, 5);
g.dispose();
//im3.setRGB(useheight / 2 - 2, useheight / 2 - 2, 5, 5, new int[] {0, 0, 0xFFFFFF, 0, 0,
//0, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFF, 0,
//0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF,
//0, 0xFFFFFF, 0xFFFFFFF, 0xFFFFFF, 0,
//0, 0, 0xFFFFFF, 0, 0}, 0, 1);
//JLabel l1 = new JLabel("1 pt", new ImageIcon(im1), JLabel.LEFT);
//JLabel l2 = new JLabel("3 pt", new ImageIcon(im2), JLabel.LEFT);
//JLabel l3 = new JLabel("5 pt", new ImageIcon(im3), JLabel.LEFT);
brushSize.addItem(new PaintIcon(im1, 1));
brushSize.addItem(new PaintIcon(im2, 3));
brushSize.addItem(new PaintIcon(im3, 5));
//brushSize.addItem("Other");
add(fore);
add(back);
add(brushSize);
PropertyChangeListener pl = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent ev) {
Object src = ev.getSource();
if (src != fore && src != back) {
return;
}
Color c = (Color) ev.getNewValue();
if (ev.getSource() == fore) {
mColor1 = c;
}
else {
mColor2 = c;
}
}
};
fore.addPropertyChangeListener("Color", pl);
back.addPropertyChangeListener("Color", pl);
fore.changeColor(Color.BLACK);
back.changeColor(Color.WHITE);
brushSize.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
System.out.println("ItemEvent");
if (ev.getID() == ItemEvent.DESELECTED) {
return;
}
System.out.println("Selected");
Object o = ev.getItem();
mBrushSize = ((PaintIcon) o).mSize;
}
});
//Graphics g = im1.getGraphics();
//g.fillOval(0, 0, 1, 1);
//BufferedImage im1 = new BufferedImage();
//BufferedImage im1 = new BufferedImage();
}
}
protected class MListener extends MouseAdapter implements MouseMotionListener {
Point mLastPoint;
public void mouseDragged(MouseEvent me) {
Graphics g = mImg.getGraphics();
if ((me.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
g.setColor(mColor1);
} else {
g.setColor(mColor2);
}
Point p = me.getPoint();
if (mLastPoint == null) {
g.fillOval(p.x - mBrushSize / 2, p.y - mBrushSize / 2, mBrushSize, mBrushSize);
//g.drawLine(p.x, p.y, p.x, p.y);
}
else {
g.drawLine(mLastPoint.x, mLastPoint.y, p.x, p.y);
//g.fillOval(p.x - mBrushSize / 2, p.y - mBrushSize / 2, mBrushSize, mBrushSize);
double angle = MathUtils.angle(mLastPoint, p);
if (angle < 0) {
angle += 2 * Math.PI;
}
double distance = MathUtils.distance(mLastPoint, p) * 1.5;
if (angle < Math.PI / 4 || angle > 7 * Math.PI / 4 || Math.abs(Math.PI - angle) < Math.PI / 4) {
for (int i = 0; i < mBrushSize / 2; i ++) {
g.drawLine(mLastPoint.x, mLastPoint.y + i, p.x, p.y + i);
g.drawLine(mLastPoint.x, mLastPoint.y - i, p.x, p.y - i);
//System.out.println("y");
//System.out.println("angle = " + angle / Math.PI * 180);
}
}
else {
for (int i = 0; i < mBrushSize / 2; i ++) {
g.drawLine(mLastPoint.x + i, mLastPoint.y, p.x + i, p.y);
g.drawLine(mLastPoint.x - i, mLastPoint.y, p.x - i, p.y);
//System.out.println("x");
}
}
//System.out.println("new = " + PaintUtils.printPoint(p));
//System.out.println("last = " + PaintUtils.printPoint(mLastPoint));
//System.out.println("distance = " + distance);
//Graphics2D g2 = (Graphics2D) g;
//g2.translate(mLastPoint.x + mBrushSize / 2, mLastPoint.y);
//g2.rotate(angle);
//g2.fillRect(0, 0, (int) Math.ceil(distance), mBrushSize);
//g2.rotate(-angle);
//g2.translate(-mLastPoint.x + mBrushSize / 2, -mLastPoint.y);
//g.setColor(Color.RED);
//g.drawRect(p.x, p.y, 1, 1);
}
mLastPoint = p;
g.dispose();
repaint();
}
public void mouseMoved(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {
mLastPoint = null;
}
}
private void handleResize() {
Dimension size = getSize();
mSizeChanged = false;
if (mImg == null) {
mImg = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
Graphics g = mImg.getGraphics();
g.setColor(getBackground());
g.fillRect(0, 0, mImg.getWidth(), mImg.getHeight());
g.dispose();
}
else {
int newWidth = Math.max(mImg.getWidth(),getWidth());
int newHeight = Math.max(mImg.getHeight(),getHeight());
if (newHeight == mImg.getHeight() && newWidth == mImg.getWidth()) {
return;
}
BufferedImage bi2 = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = bi2.getGraphics();
g.setColor(getBackground());
g.fillRect(0, 0, bi2.getWidth(), bi2.getHeight());
g.drawImage(mImg, mImg.getWidth(), mImg.getHeight(), null);
g.dispose();
mImg = bi2;
}
}
public JToolBar getToolBar() {
if (mToolBar == null) {
mToolBar = new ToolBar();
}
return mToolBar;
}
private ToolBar mToolBar;
public static void main (String args[]) {
PaintArea pa = new PaintArea();
JPanel parent = new JPanel();
parent.setLayout(new BorderLayout());
parent.add(pa, BorderLayout.CENTER);
pa.setPreferredSize(new Dimension(150, 150));
parent.add(pa.getToolBar(), BorderLayout.NORTH);
WindowUtilities.visualize(parent);
}
protected class CListener extends ComponentAdapter {
public void componentResized(ComponentEvent ce) {
mSizeChanged = true;
}
}
}