【问题标题】:undo method for a paint program (Java)绘画程序的撤消方法(Java)
【发布时间】:2016-09-20 09:35:43
【问题描述】:

我正在尝试为基本绘图程序创建撤消方法。目前,您可以更改画笔的大小和颜色以及擦除。我试图通过将前一个屏幕保存为图像(最后一个)来撤消,当调用撤消时,绘制该图像。我尝试了几件事,但没有任何效果。简单地“最后”绘制图像会产生与 clear 方法相同的效果。有什么想法吗?:

import java.applet.*;
import java.util.*;
import java.awt.*;
import java.lang.Object.*;

public class Paint extends Applet
{
private int x;
private int y;
private int size = 10;
private int sides = 200;
private int color = 0;
private Rectangle red, orange, yellow, green, blue, purple, pink, black;
private Rectangle triangle, square, pentagon, hexagon, octagon, circle;
private Rectangle small, medium, large;
private Rectangle eraser, clear, undo;
private Rectangle menuBar;
private Image last;
private Graphics g2;

//defines rectangles
public void init()
{
  setSize(400,600);

  red = new Rectangle(0,0,25,25);
  orange = new Rectangle(0,25,25,25);
  yellow = new Rectangle(0,50,25,25);
  green = new Rectangle(0,75,25,25);
  blue = new Rectangle(0,100,25,25);
  purple = new Rectangle(0,125,25,25);
  pink = new Rectangle(0,150,25,25);
  black = new Rectangle(0,175,25,25);

  triangle = new Rectangle(0,200,25,25);
  square = new Rectangle(0,225,25,25);
  pentagon = new Rectangle(0,250,25,25);
  hexagon = new Rectangle(0,275,25,25);
  octagon = new Rectangle(0,300,25,25);
  circle = new Rectangle(0,325,25,25);

  small = new Rectangle(0,355,25,25);
  medium = new Rectangle(0,370,50,50);
  large = new Rectangle(0,420,100,100);

  eraser = new Rectangle(0,520,50,25);
  clear = new Rectangle(0,545,60,30);
  undo = new Rectangle(0,575,60,30);

  menuBar = new Rectangle(0,0,70,650);
}

//paints the blocks of color in the menu bar
public void paintColors(Graphics g)
{
  g.setColor(Color.red);
  g.fillRect(0,0,25,25);
  g.setColor(Color.orange);
  g.fillRect(0,25,25,25);
  g.setColor(Color.yellow);
  g.fillRect(0,50,25,25);
  g.setColor(Color.green);
  g.fillRect(0,75,25,25);
  g.setColor(Color.blue);
  g.fillRect(0,100,25,25);
  g.setColor(new Color(160,32,240));
  g.fillRect(0,125,25,25);
  g.setColor(Color.pink);
  g.fillRect(0,150,25,25);
  g.setColor(Color.black);
  g.fillRect(0,175,25,25);
}

//paints the shapes, eraser, clear, and undo in the menu bar
public void paintShapes(Graphics g)
{
  g.setColor(Color.black);
  Utility.fillTri(g,12,212,25);
  g.fillRect(2,227,20,20);
  Utility.fillPent(g,12,262,25);
  Utility.fillHex(g,12,287,25);
  Utility.fillOct(g,12,312,25);
  Utility.fillPoly(g,12,337,25,300);

  g.fillOval(2,355,10,10);
  g.fillOval(2,370,50,50);
  g.fillOval(2,420,100,100);

  g.setColor(Color.black);
  g.drawRect(1,521,52,26);
  g.setColor(Color.pink);
  g.fillRect(2,522,40,25);

  g.setColor(Color.black);
  g.setFont(new Font("Arial",Font.PLAIN,20));
  g.drawString("CLEAR",2,580);
  g.drawString("UNDO",2,610);
}

public void paint(Graphics g)
{ 
  g2 = getGraphics();

  g2.setColor(Color.white);
  g2.fillRect(0,0,60,getHeight());
  paintColors(g2);
  paintShapes(g2);

  draw(g2);
}

public void draw(Graphics g)
{
  getColor(g);

  Utility.fillPoly(g,x,y,size,sides); //fills a regular polygon with specified center, size, and number of sides
}

public boolean mouseDown(Event e, int xx, int yy)
{
    x = xx;
    y = yy;

  if(red.inside(xx,yy))
     color = 0;
  else if(orange.inside(xx,yy))
     color = 1;
  else if(yellow.inside(xx,yy))
     color = 2;
  else if(green.inside(xx,yy))
     color = 3;
  else if(blue.inside(xx,yy))
     color = 4;
  else if(purple.inside(xx,yy))
     color = 5;
  else if(pink.inside(xx,yy))
     color = 6;
  else if(black.inside(xx,yy))
     color = 7;

  if(triangle.inside(xx,yy))
     sides = 3;
  else if(square.inside(xx,yy))
     sides = 4;
  else if(pentagon.inside(xx,yy))  
     sides = 5;
  else if(hexagon.inside(xx,yy))
     sides = 6;
  else if(octagon.inside(xx,yy))
     sides = 7;
  else if(circle.inside(xx,yy))
     sides = 200;

  if(small.inside(xx,yy))
     size = 10;
  else if(medium.inside(xx,yy))
     size = 50;
  else if(large.inside(xx,yy))
     size = 100;

  if(eraser.inside(xx,yy))
     color = 8;

  if(clear.inside(xx,yy))  
     clear(g2);
  else if(undo.inside(xx,yy))
     undo(g2);

  if(!menuBar.inside(xx,yy))
     last = createImage(getWidth(),getHeight());

    return true;
}

public boolean mouseDrag(Event e, int xx, int yy)
{
    x = xx;
    y = yy;
  if(!menuBar.inside(xx,yy))
     repaint();

    return true;
}

public void update(Graphics g)
{
    paint(g);
}

public void clear(Graphics g)
{
  color = 8;
  getColor(g);
  g.fillRect(0,0,getWidth(),getHeight());
  color = 0;
  repaint();
}

public void undo(Graphics g)
{

{

public int getColor(Graphics g)
{
  switch(color){
  case 0: g.setColor(Color.red);
  break;
  case 1: g.setColor(Color.orange);
  break;
  case 2: g.setColor(Color.yellow);
  break;
  case 3: g.setColor(Color.green);
  break;
  case 4: g.setColor(Color.blue);
  break;
  case 5: g.setColor(new Color(160,32,240));
  break;
  case 6: g.setColor(Color.pink);
  break;
  case 7: g.setColor(Color.black);
  break;
  case 8: g.setColor(new Color(238,238,238));
  break;
  }

  return color;
}
}

【问题讨论】:

  • 关于代码质量的旁注:你长长的 if/else 状态......只是糟糕的代码。摆脱它,否则维护将很快变成你的噩梦。对于实际问题:您可能想研究 Command 模式。而不是保存整个图像(这听起来像是一个非常消耗资源的想法),您可能希望确保对绘画的每个“更改”......实际上是某种命令对象;记住:你确实画了一个圆,x,y,半径,颜色。您将所有“已应用”的命令放在一个队列中; “撤消”意味着删除最后一个条目。
  • 不,它确实有效,您必须包含所有内容
  • gpasch,它确实有效。我现在在我的电脑上运行它。可以编译运行,但是undo方法出现逻辑错误。
  • 您是否考虑过使用UndoManager?这将使每个“编辑”都可以自给自足地删除自身并重新实例化自身。在这种情况下,编辑会知道自己的 ID 并告诉根面板删除它。
  • undomanager 可以和图形一起使用吗?我快速查看了它,我认为如果不更改我的其他代码的重要部分,我将无法使用它

标签: java graphics paint undo


【解决方案1】:

我强烈建议使用Command 模式的一些变体来处理历史记录。

Swing 有一个简单的历史管理器,名为 UndoManager。通常它与文本编辑器一起使用,但它也适用于自定义命令。

如果您不想使用 Swing 或 UndoManager 不符合您的要求,请尝试使用替代的独立解决方案或实施您自己的解决方案。 I also implemented my own 用于大型跨平台应用程序。

因此,您应该将所有编辑方法封装到实现公共接口(例如CommandUndoableEdit)并具有“do”和“undo”方法的命令类中。

与只需要存储有关编辑的最少信息的文本文档相比,为图形实现命令更难。将原始图像中更改区域的矩形存储在“do”上并在“undo”上恢复。

【讨论】:

    【解决方案2】:

    即使 mousedown 不会更改图像,您也会在每次 mousedown 时添加到撤消列表。

    因此,当您单击撤消选项时,您首先会保存图像,然后再恢复相同的图像。

    您应该只在用户实际修改图像之前保存到撤消列表。

    【讨论】:

    • 好的,谢谢。这确实有帮助。但是,undo 方法目前只是完全清除屏幕。
    猜你喜欢
    • 2014-06-29
    • 2011-04-26
    • 2015-03-30
    • 2014-01-16
    • 1970-01-01
    • 2011-09-11
    • 2011-05-21
    • 1970-01-01
    • 2014-12-21
    相关资源
    最近更新 更多