swing Java创建笔刷笔划动作
当你用任何画笔用任何画笔画一条手绘线时,它最终会将该画笔的多个点叠加在一起,形成一个画笔笔划
例如,当你拖动鼠标时,一个基本的笔划会叠加1个像素。 在更高级的应用程序中,你有一个画笔,它只是一个奇特的形状,比如说:一个星星,用“星星画笔”在画布上划动,只会使绘画应用程序在你将鼠标拖动到画布上时绘制多个星星。 如果我错了,请纠正我
我已经实现了“画笔”(即基本圆圈),每当用户在画布上拖动鼠标,同时按住鼠标左键时,应用程序就会为每个新的鼠标位置绘制一个圆圈
我的问题是“撤销功能”,如果你这么说的话
当我撤销一个动作时,我的应用程序只删除最后绘制的形状(圆),而我希望它删除从用户第一次按下鼠标左键到释放的整个徒手绘制(形状/圆的集合)
如何将一组形状对象“打包”为一个? 还有一个问题是重新绘制所有这些圆圈,我希望重新绘制30000个圆圈的速度要快,就像一个BuffereImage
我已经使用BuffereImage作为图像的背景
每一个超过50岁的形状都会永久存储在BuffereImage背景中
目前,我将最后50个形状对象存储在ArrayList中,第51个(最老的)永久存储在BuffereImage中。 所以用户不能撤销50个动作,而是撤销50个形状
谢谢!
精简代码示例:
public class GraphicPanel extends JComponent{
private int x = 0;
private int y = 0;
private int compXLen = 100;
private int compYLen = 100;
private boolean isCompFilled = false;
private boolean isAreaToBePainted = false;
private boolean isFocused = false;
private Shape ghost;
private ArrayList<Shape> shapeBuffer = new ArrayList<Shape>();
private BufferedImage img = new BufferedImage( PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB );
private static final int PREF_W = 800;
private static final int PREF_H = 500;
@Override
public void paintComponent( Graphics gPlain ){
super.repaint();
Graphics2D g = (Graphics2D)gPlain;
//paint background
if (img != null){
g.drawImage(img, 0, 0, null);
}
ghost = new Ellipse2D.Double( x-( compXLen/2 ), y-( compYLen/2 ), compXLen, compYLen );
if( isAreaToBePainted ){
//add ghost Shape to ArrayList
add( g, ghost )
}
//paint arrayList
for( Shape s : shapeBuffer ){
g.fill( s );
}
if( isFocused ){
// draw ghost shape
g.draw( ghost );
}
}
/**
* adds circles to arrayList
*/
private void add( Graphics2D g, Shape s ){
//fetch last arrayList element in Shape shp
//add ghost shape at the top of arrayList
Graphics2D g2 = img.createGraphics();
shapeBuffer.add( shp );
g2.fill( shp );
g2.dispose();
}
public void clearArea(){
shapeBuffer = new ArrayList<Shape>();
img = new BufferedImage( PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB );
repaint();
}
private class GraphicPanelMouseListen implements MouseListener, MouseMotionListener{
/**
* @param e Mouse Event
* @since 0.1
*/
@Override
public void mouseClicked( MouseEvent e ){}
public void mousePressed( MouseEvent e ){
x = e.getX();
y = e.getY();
isAreaToBePainted = true;
repaint();
}
public void mouseReleased( MouseEvent e ){}
public void mouseEntered( MouseEvent e ){
isFocused = true;
}
public void mouseExited( MouseEvent e ){
isFocused = false;
repaint();
}
public void mouseDragged( MouseEvent e ){
isAreaToBePainted = true;
x = e.getX();
y = e.getY();
repaint();
}
public void mouseMoved( MouseEvent e ){
x = e.getX();
y = e.getY();
repaint();
}
}//public class GraphicPanelMouseListen implements MouseListener
}//public class GraphicPanel
# 1 楼答案
通过将每个完成的画笔笔划或相关的任何动作存储在自己的图像中,可以避免完全使用这些列表。然后你可以按制作顺序将它们分层。这将是更少的,你可以很容易地定义多少行动在过去你想有,而最底部的一个包含一切不符合历史
Pixel blit是一种相对快速的操作,与处理形状的操作不同,通过使用VolatileImage而不是缓冲图像来收集历史中的所有动作,可以轻松地提高速度
在我看来,这种方法更快,并且对未来添加的操作限制更少。你可以很容易地将某些层标记为不可见,并在历史中来回移动,比如在Photoshop中,但不依赖于所述层的实际内容