4

我试图在 Java 中的 Canvas 中绘制两条线,分别调用两个方法,但是当我绘制第二条线时,第一条线消失(Java 清除屏幕)。我怎样才能避免这种情况?我想看看这两条线。我看过画图教程(如何在 Windows 上制作像画图这样的程序),其中用户使用鼠标画线,当画出一条线时,另一条线不会消失。他们只是调用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();
            }
        });
    }
}
4

2 回答 2

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;
}
于 2013-04-06T17:39:43.320 回答
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);
        }
    }
}
于 2013-04-06T18:01:58.427 回答