如何在不清除以前的图形的情况下从paintComponent更新图形?

时间:2019-03-13 12:52:25

标签: java swing turtle-graphics

这段代码是我使用的乌龟图形版本,它使用JTextField中的命令进行绘制。现在,通过使用图形方法drawLine在乌龟已移动的位置绘制线来绘制图形。问题是每次我单击绘制按钮或输入6进行绘制时,repaint方法都会清除以前绘制的线条,而只会绘制当前线条

    //1 - turtle up
    //2 - turtle down/draw
    //3 - turn right
    //4 - turn left
    //5 - move forward a number of steps
    //6 - display drawing
    import java.awt.Graphics;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JTextField;
    import javax.swing.JButton;
    import javax.swing.Box;
    import javax.swing.JPanel;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;

    public class TurtleGraphics2D extends JPanel implements ActionListener
    {
      private static final int FLOORSIZE = 200;
      private static Box box;
      private JTextField textField;
      private JButton drawButton;
      private int prevX = 0;
      private int prevY = 0;
      private int currentXPosition = 0; 
      private  int currentYPosition = 0; 
     private   int command, steps = 0;
      private  int leftCount = 0; //to know how many times the turtle has                 
     //turned left and to reflect left in reference to north
       private  int rightCount = 0; //to know how many times the turtle has          
     //turned right and to reflect right in reference to north
       private  boolean isDown = false; //to know when pen is up or down
       private boolean isLeft = false; //to know when turtle has turned left
        private boolean isRight = false; //to know when turtle has turned                            
    //right

       public TurtleGraphics2D()
       {

         box = Box.createVerticalBox();

         textField = new JTextField("Enter Command...");
         drawButton = new JButton("Display Drawing");

         box.add(textField);
         box.add(drawButton);

         textField.addActionListener(this);
         drawButton.addActionListener(this);
       }

       public void paintComponent(Graphics g)
       {
         super.paintComponent(g);

         if (isDown)
           g.drawLine(prevY,prevX,currentYPosition,currentXPosition);

         prevY = currentYPosition;
         prevX = currentXPosition;
       }

       public void actionPerformed(ActionEvent event)
       {
         if (event.getSource() == textField)
         {
           try
           {
           command = Integer.parseInt(textField.getText());
           textField.setText("");

           switch(command)
         {
           case 1:
             isDown = false;
             break;
           case 2:
    isDown = true;
    break;
  case 3:
    isRight = true;
    isLeft = false;
    rightCount++;
    if (rightCount > 4)
      rightCount = 1;
    System.out.println("Right Count: "+rightCount);
    break;
  case 4:
    isLeft = true;
    isRight = false;
    leftCount++;
    if (leftCount > 4)
      leftCount = 1;
    System.out.println("Left Count: "+leftCount);
    break;
  case 5:
    steps = Integer.parseInt(JOptionPane.showInputDialog("Steps: "));
    for(int i = 0; i < steps; ++i)
    {

      if (isRight == true)
      {
        if ((rightCount == 3 && leftCount == 0)||(rightCount == 1 && leftCount == 2)||(rightCount == 2 && leftCount == 3)||(rightCount == 3 && leftCount == 4)||(rightCount == 4 && leftCount == 1)) //cursor upward
        {
          if (currentXPosition > 0) // this condition ensures ArrayIndexOutOfBoundsException is avoided
             currentXPosition--;
        }
         if ((rightCount == 0 && leftCount == 0)||(rightCount == 4 && leftCount == 4)||(rightCount == 1 && leftCount == 1)||(rightCount == 4 && leftCount == 0)||(rightCount == 2 && leftCount == 2)) //cursor right
        {
           if (currentYPosition < FLOORSIZE) // this condition ensures ArrayIndexOutOfBoundsException is avoided
             currentYPosition++;
        }
         if ((rightCount == 2 && leftCount == 0)||(rightCount == 1 && leftCount == 3)||(rightCount == 4 && leftCount == 2)||(rightCount == 2 && leftCount == 4)||(rightCount == 3 && leftCount == 1)) //cursor left
        {
           if (currentYPosition > 0)
             currentYPosition--;
        }
          if ((rightCount == 1 && leftCount == 0)||(rightCount == 2 && leftCount == 1)||(rightCount == 1 && leftCount == 4)) //cursor left
        {
            if (currentXPosition < FLOORSIZE)
              currentXPosition++;
        }
      }
        if (isLeft == true)
      {
        if ((rightCount == 3 && leftCount == 0)||(rightCount == 1 && leftCount == 2)||(rightCount == 2 && leftCount == 3)||(rightCount == 3 && leftCount == 4)||(rightCount == 4 && leftCount == 1)) //cursor upward
        {
          if (currentXPosition > 0)
             currentXPosition--;
        }
         if ((rightCount == 0 && leftCount == 0)||(rightCount == 4 && leftCount == 4)||(rightCount == 1 && leftCount == 1)||(rightCount == 4 && leftCount == 0)||(rightCount == 2 && leftCount == 2)) //cursor right
        {
           if (currentYPosition < FLOORSIZE)
             currentYPosition++;
        }
         if ((rightCount == 2 && leftCount == 0)||(rightCount == 1 && leftCount == 3)||(rightCount == 4 && leftCount == 2)||(rightCount == 2 && leftCount == 4)||(rightCount == 3 && leftCount == 1)) //cursor left
        {
           if (currentYPosition > 0)
             currentYPosition--;
        }
          if ((rightCount == 1 && leftCount == 0)||(rightCount == 2 && leftCount == 1)||(rightCount == 1 && leftCount == 4)) //cursor left
        {
            if (currentXPosition < FLOORSIZE)
              currentXPosition++;
        }
      }
      if (isRight == false && isLeft == false && rightCount == 0 && leftCount == 0)//default/initial direction
      {
        currentYPosition++;
      }
    }
    break;
  case 6:
    repaint();
    break;
  default:
    break;
}

  }
  catch(IllegalArgumentException ex)
  {
    JOptionPane.showMessageDialog(null,"Invalid Command","Error Message",JOptionPane.ERROR_MESSAGE);
    System.err.println("Invalid command");
  }
}
else if (event.getSource() == drawButton)
{
  repaint();
}
       }
       public static void main(String args[])
       {
JFrame frame = new JFrame();
TurtleGraphics2D panel = new TurtleGraphics2D();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);

frame.add(box, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);

frame.setVisible(true);
       }
     }

first line drawn
second line drawn clearing the previous line when they should both be displayed

1 个答案:

答案 0 :(得分:0)

以下是使用the link that @camickr provided in the comments中讨论的 active 方法对代码进行的简化(虽然功能相同)的重做。此实现维护自定义ArrayList对象的Line,可用于在repaint上重新创建图形:

import java.awt.Graphics;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.Box;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import java.util.ArrayList;

// 1 - turtle up
// 2 - turtle down/draw
// 3 - turn right
// 4 - turn left
// 5 - move forward a number of steps
// 6 - display drawing

class Line {
    int startX;
    int startY;
    int endX;
    int endY;

    Line(int startX, int startY, int endX, int endY)
    {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;
    }
}

public class TurtleGraphics2D extends JPanel implements ActionListener
{
    private static final int FLOORSIZE = 400;

    private static Box box;
    private JTextField textField;
    private JButton drawButton;
    private int currentXPosition = 0; 
    private int currentYPosition = 0; 
    private int heading = 0;  // initial heading is South
    private boolean isDown = false; // to know when pen is up or down

    private ArrayList<Line> lines = new ArrayList<>(); // a collection of lines to (re)draw

    public TurtleGraphics2D()
    {
        box = Box.createVerticalBox();

        textField = new JTextField("Enter Command...");
        drawButton = new JButton("Display Drawing");

        box.add(textField);
        box.add(drawButton);

        textField.addActionListener(this);
        drawButton.addActionListener(this);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        for (Line line: lines)
        {
            g.drawLine(line.startX, line.startY, line.endX, line.endY);
        }
    }

    public void actionPerformed(ActionEvent event)
    {
        if (event.getSource() == textField)
        {
            try
            {
                int command = Integer.parseInt(textField.getText());
                textField.setText("");

                switch(command)
                {
                    case 1:
                        isDown = false;
                        break;
                    case 2:
                        isDown = true;
                        break;
                    case 3: // right / clockwise
                        if (++heading > 3)
                        {
                            heading -= 4;
                        }
                        break;
                    case 4: // left / counterclockwise
                        if (--heading < 0)
                        {
                            heading += 4;
                        }
                        break;
                    case 5:
                        int steps = Integer.parseInt(JOptionPane.showInputDialog("Steps: "));

                        int prevX = currentXPosition;
                        int prevY = currentYPosition;

                        for (int i = 0; i < steps; i++)
                        {
                            if (heading == 0) // cursor South
                            {
                                // this condition ensures ArrayIndexOutOfBoundsException is avoided
                                if (++currentYPosition > FLOORSIZE)
                                {
                                    currentYPosition--;
                                }
                            }
                            else if (heading == 1) // cursor West
                            {
                                if (--currentXPosition < 0)
                                {
                                    currentXPosition++;
                                }
                            }
                            else if (heading == 2) // cursor North
                            {
                                if (--currentYPosition < 0)
                                {
                                    currentYPosition++;
                                }
                            }
                            else if (heading == 3) // cursor East
                            {
                                if (++currentXPosition > FLOORSIZE)
                                {
                                    currentXPosition--;
                                }
                            }
                        }

                        if (isDown)
                        {
                            lines.add(new Line(prevX, prevY, currentXPosition, currentYPosition));
                        }

                        break;
                    case 6:
                        repaint();
                        break;
                    default:
                        break;
                    }

                }
                catch(IllegalArgumentException ex)
                {
                    JOptionPane.showMessageDialog(null, "Invalid Command", "Error Message", JOptionPane.ERROR_MESSAGE);
                    System.err.println("Invalid command");
                }
            }
            else if (event.getSource() == drawButton)
            {
                repaint();
            }
        }

    public static void main(String args[])
    {
        JFrame frame = new JFrame();
        TurtleGraphics2D panel = new TurtleGraphics2D();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);

        frame.add(box, BorderLayout.NORTH);
        frame.add(panel, BorderLayout.CENTER);

        frame.setVisible(true);
    }
}

enter image description here

以下结果:4 5 <150> 3 5 <150> 2 5 <50> 4 5 <50> 4 5 <50> 4 5 <50>