调用paint方法时Java清除屏幕 - 如何避免?

时间:2013-04-06 17:33:45

标签: java screen paint clear java-canvas

我正在尝试在Java中使用Canvas绘制两行,分别调用两个方法,但是当我绘制第二行时,第一行消失(Java清除屏幕)。我怎么能避免这种情况?我想看两条线。我已经看过油漆教程(如何制作像Windows上的Paint这样的程序)用户使用鼠标绘制线条,当绘制一条线时,另一条线不会消失。他们只是调用paint方法,它不会清除屏幕。

如果有人能帮助我,我将不胜感激。 感谢。

查看课程

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;

public class CircuitTracePlotView extends JFrame {


    private CircuitTracePlot circuitTracePlot;

    public  CircuitTracePlotView() {


        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        this.getContentPane().add(circuitTracePlot = new CircuitTracePlot(), BorderLayout.CENTER);
        this.pack();
        this.setSize(250,250);
        this.setLocationRelativeTo(null);

        this.setVisible(true);
        circuitTracePlot.drawLine();
        circuitTracePlot.drawOval();
    }


}

class CircuitTracePlot extends Canvas {

    private final static short LINE = 1;
    private final static short OVAL = 2;
    private int paintType;

    private int x1;
    private int y1;
    private int x2;
    private int y2;

    public CircuitTracePlot() {
        this.setSize(250,250);
        this.setBackground(Color.WHITE);

    }

    private void setPaintType(int paintType) {
        this.paintType = paintType;
    }

    private int getPaintType() {
        return this.paintType;
    }

    public void drawLine() {
        this.setPaintType(LINE);
        this.paint(this.getGraphics());
    }

    public void drawOval() {
        this.setPaintType(OVAL);
        this.paint(this.getGraphics());
    }

    public void repaint() {
        this.update(this.getGraphics());
    }

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

    public void paint(Graphics g) {
        switch (paintType) {
        case LINE:
            this.getGraphics().drawLine(10, 10, 30, 30);            
        case OVAL:
            this.getGraphics().drawLine(10, 20, 30, 30);
        }


    }


}

主要课程

import javax.swing.SwingUtilities;

import view.CircuitTracePlotView;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                CircuitTracePlotView cr = new CircuitTracePlotView();
            }
        });
    }
}

2 个答案:

答案 0 :(得分:4)

  • 您几乎不应该直接致电paint(...)。我可以算一下我需要做的时间。
  • 不要通过调用组件上的getGraphics()来获取Graphics对象,因为它将返回非持久的Graphics对象。而是在BufferedImage中绘制并在paint方法中显示或在paint方法中绘制(如果是AWT)。
  • 由于这是一个Swing GUI,因此不要使用AWT组件进行绘制。使用JPanel并覆盖paintComponent(...)方法,而不是paint(...)方法。否则你将失去Swing图形的所有好处,包括自动双缓冲。
  • super.paintComponent(g)方法应该在paintComponent(Graphics g)覆盖中调用,通常作为此方法内部的第一个方法调用。这使组件可以自己进行管家绘画,包括擦除需要删除的绘图。
  • 阅读有关Swing图形的教程,因为大部分内容都在那里得到了很好的解释。例如,请看这里:

修改

  • 为了保持图像的持久性,我建议您绘制一个BufferedImage,然后在JPanel的paintComponent(...)方法中显示该图像。
  • 或者另一种选择是创建一个Shape对象集合,可能是一个ArrayList<Shape>并用你想要绘制的Shapes填充它,然后在paintComponent(...)方法中将Graphics对象强制转换为一个Graphics2D对象并迭代遍历Shape集合,在迭代时用g2d.draw(shape)绘制每个形状。

由于Trash发布了他的代码,......

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class CircuitTracePlot2 extends JPanel {

   private static final int PREF_W = 250;
   private static final int PREF_H = PREF_W;

   private int drawWidth = 160;
   private int drawHeight = drawWidth;
   private int drawX = 10;
   private int drawY = 10;
   private PaintType paintType = PaintType.LINE;

   public CircuitTracePlot2() {

   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public void setPaintType(PaintType paintType) {
      this.paintType = paintType;
      repaint();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (paintType == null) {
         return;
      }
      switch (paintType) {
      case LINE:
         g.drawLine(drawX, drawY, drawWidth, drawHeight);
         break;
      case OVAL:
         g.drawOval(drawX, drawY, drawWidth, drawHeight);
         break;
      case SQUARE:
         g.drawRect(drawX, drawY, drawWidth, drawHeight);

      default:
         break;
      }
   }

   private static void createAndShowGui() {
      final CircuitTracePlot2 circuitTracePlot = new CircuitTracePlot2();

      JFrame frame = new JFrame("CircuitTracePlot2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(circuitTracePlot);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);

      int timerDelay = 2 * 1000;
      new Timer(timerDelay , new ActionListener() {
         private int paintTypeIndex = 0;

         @Override
         public void actionPerformed(ActionEvent arg0) {
            paintTypeIndex++;
            paintTypeIndex %= PaintType.values().length;
            circuitTracePlot.setPaintType(PaintType.values()[paintTypeIndex]);
         }
      }).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

enum PaintType {
   LINE, OVAL, SQUARE;
}

答案 1 :(得分:2)

这是您的程序的变体,它实现了@Hovercraft的大部分有用建议。尝试将对setPaintType()的调用注释掉以查看效果。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/** @see http://stackoverflow.com/a/15854246/230513 */
public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                CircuitTracePlotView cr = new CircuitTracePlotView();
            }
        });
    }

    private static class CircuitTracePlotView extends JFrame {

        private CircuitTracePlot plot = new CircuitTracePlot();

        public CircuitTracePlotView() {
            this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            plot.setPaintType(CircuitTracePlot.OVAL);
            this.add(plot, BorderLayout.CENTER);
            this.pack();
            this.setLocationRelativeTo(null);
            this.setVisible(true);
        }
    }

    private static class CircuitTracePlot extends JPanel {

        public final static short LINE = 1;
        public final static short OVAL = 2;
        private int paintType;

        public CircuitTracePlot() {
            this.setBackground(Color.WHITE);
        }

        public void setPaintType(int paintType) {
            this.paintType = paintType;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            switch (paintType) {
                case LINE:
                    g.drawLine(10, 10, 30, 30);
                case OVAL:
                    g.drawOval(10, 20, 30, 30);
                default:
                    g.drawString("Huh?", 5, 16);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(250, 250);
        }
    }
}