java - 在画布上使用鼠标绘制颜料的有效方法
问题描述
我有一Brush
堂课
final class Brush
{
private final int size;
private final Color color;
private final Ellipse2D.Double blob=new Ellipse2D.Double();
private Brush(int size,Color color)
{
this.size=size;
this.color=color;
}
void paint(Graphics2D g2d,Point location)
{
g2d.setColor(color);
blob.setFrame(location.x-(size/2.0),location.y-(size/2.0),size,size);//Translate ecllipse so that the centre of it's bounding box is exactly at the cursor location for more accurate blobs
g2d.fill(blob);
}
}
我有一个Blob
类,它跟踪用户当前的画笔设置以及用户之前拖动鼠标的位置,以便记住在那里绘制一个 blob。
final class Blob
{
final Brush brush;
final Point location;
private Blob(Brush brush,Point location)
{
this.brush=brush;
this.location=location;
}
private void paint(Graphics2D g){brush.paint(g,location);}
}
最后我的绘画逻辑非常简单。
每当用户拖动鼠标时,使用当前画笔设置在当前位置添加一个 blob,并在内部paint()
循环所有 blob 并重绘它们。
final class Painter extends Canvas
{
private Brush brush=new Brush(5,Color.red);//Can Change
private final ArrayList<Blob> blobs=new ArrayList();
private Painter(){addMouseMotionListener(new Dragger());}
@Override
public void paint(Graphics g)
{
super.paint(g);
blobs.forEach(blob->blob.paint(g));
}
private final class Dragger extends MouseAdapter
{
@Override
public void mouseDragged(MouseEvent m)
{
blobs.add(brush,m.getPoint());
repaint();
}
}
}
您已经可以在此处看到问题所在。列表的大小呈指数增长,我的应用程序迅速变慢。有没有更有效的方法来做到这一点?
解决方案
更有效的方法是使用 BufferedImage 进行绘图,而不是在 paintComponent 中绘制 BufferedImage
取自PaintArea的代码:
public void paintComponent(Graphics g) {
if (mSizeChanged) {
handleResize();
}
g.drawImage(mImg, 0, 0, null);
}
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;
}
@SuppressWarnings("unused")
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);
}
}
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);
}
}
}
mLastPoint = p;
g.dispose();
repaint();
}
public void mouseMoved(MouseEvent me) {}
public void mouseReleased(MouseEvent me) {
mLastPoint = null;
}
}
推荐阅读
- javascript - 在 JavaScript 中使用 usb 签名创建 CADES-BES 签名
- android - 与另一台相比,BLE 广告扫描在一台 Andriod 设备上扫描非常缓慢的广告 - Android V9 与 Android V7
- mongoose - 与另一只猫鼬添加收集数据
- terraform - Terraform 如何读取运行时值 ..Cloudformation 等效于 Instrinsic 函数
- svn - 在 phabricator 上导入 SVN 存储库卡在 0.00%
- javascript - 用于图表/图形电生理数据的 Javascript 库 - 数小时内的大数据
- asp.net - 如何使用 ASP.Net React SPA 在 Cypress 中以编程方式登录
- r - 如何在 R 中旋转 `grid` `grob` 或 `grobTree` 对象?
- swift - Swift 5.3 macOS - 加载本地 HTML
- arrays - AJAX Express 在客户端接收数组