最好处理2个覆盖实时更新的面板?

时间:2011-09-09 17:54:05

标签: java swing

在非常基本的术语中,我有一个面板逐个像素地绘制一条线,并且正在实时更新。除此之外,我想要另一个面板,它围绕当前像素绘制一个框,但稍后会自行清除。两者都是实时的

我目前的情况是包含JPAnel的OverlayLayout。底部面板具有使用从Graphics2D获取的JPanel对象绘制的线条。顶部面板后面的框也是使用从其JPanel获取的Graphics2D对象绘制的。

这个系统中的问题很多。由于我只是单独绘制Graphics2D对象并且没有覆盖JPanel的paint(),所以当面板需要重新绘制时,所有线条都会丢失,我想我会反对Swing的线程模型只有一个线程更新屏幕。我还没有让顶部面板正常工作,它只是不断清理屏幕,不会让底部面板画一条线。

处理这种情况的最佳方法是什么?我对图像处理和Swing中图像的低级显示几乎没有经验,我只知道基础知识。我听说过BufferedImage,但不知道该图片放在哪里,如果稍后更改它会更新,这样做的效率,以及它缓冲的事实吓跑了我。我不知道该用什么

有人能指出我需要用什么来实现这个目标的正确方向吗?

2 个答案:

答案 0 :(得分:4)

您可以使用合适的Shape累积积分,例如GeneralPath,如LissajousPanel所示。使用javax.swing.Timer进行定期更新,并使用周围的矩形突出显示最近添加的点。

答案 1 :(得分:3)

我建议

  • 您没有通过getGraphics获取JPanel的Graphics或Graphics2D对象,因为此对象不是稳定的,并且一旦组件因任何原因重新绘制后将无法工作。
  • 你改为在一个JPanel的paintComponent方法中完成所有绘图,但首先在该方法中调用super的方法。
  • 你再次只画一张JPanel,而不是两张,
  • 您在BufferedImage中绘制线条,因为这是图像中更永久的部分。
  • 通过createGraphics方法获取BufferedImage的Graphics2D对象
  • 使用它时,你正确处理了BufferedImage的Graphics对象,以节省资源。
  • 在JPanel的paintComponent方法中显示BufferedImage(在首先调用super方法之后)
  • 你使用int类变量直接在paintComponent中绘制你的盒子,图像中更短暂的部分,告诉paintComponent在哪里绘制,也许是一个类布尔变量来告诉如果要绘制
  • 最重要的是,你查看关于Swing图形的教程,为了正确地做到这一点,你必须抛弃所有旧的假设,并从头开始学习正确的方法(我们都必须这样做)。 / LI>

例如:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

@SuppressWarnings("serial")
public class BufferedImageEg extends JPanel {
   private static final int BI_WIDTH = 700;
   private static final int BI_HEIGHT = 500;
   private static final Color BACKGROUND = new Color(255, 255, 240);
   private static final int THIS_PT_WIDTH = 12;
   private static final int THIS_PT_HEIGHT = THIS_PT_WIDTH;
   private static final float THIS_PT_STROKE_WIDTH = 2f;
   private static final Color THIS_PT_BORDER_COLOR = Color.red;
   private static final Color THIS_PT_FILL_COLOR = new Color(250, 250, 0, 125);
   private static final int TIMER_DELAY = 30;
   private static final int X_MIN = 0;
   private static final int X_MAX = 100;
   private static final double X_STEP = 0.1;
   private static final double X_SCALE = (double) BI_WIDTH
         / ((double) X_MAX - X_MIN);
   private static final double Y_SCALE = 8;
   private static final float LINE_WIDTH = 4;
   private static final Color LINE_COLOR = Color.blue;

   private Point lastPoint = null;
   private Point thisPoint = null;

   private BufferedImage bImage = new BufferedImage(BI_WIDTH, BI_HEIGHT,
         BufferedImage.TYPE_INT_RGB);
   private double xValue = X_MIN;

   public BufferedImageEg() {
      Graphics biG = bImage.getGraphics();
      biG.setColor(BACKGROUND);
      biG.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
      setBackground(BACKGROUND);
      new Timer(TIMER_DELAY, new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            timerActionPerformed(e);
         }
      }).start();
   }

   private void timerActionPerformed(ActionEvent e) {
      if (xValue <= X_MAX) {
         lastPoint = thisPoint;
         double tempX = xValue;
         double yValue = function(xValue);

         tempX *= X_SCALE;
         yValue *= Y_SCALE;
         yValue = BI_HEIGHT / 2.0 - yValue;

         thisPoint = new Point((int) tempX, (int) yValue);

         if (lastPoint != null) {
            drawInBufferedImage();
         }

         xValue += X_STEP;
      } else {
         ((Timer) e.getSource()).stop();
         thisPoint = null;
      }
      repaint();
   }

   private void drawInBufferedImage() {
      Graphics2D g2 = bImage.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setStroke(new BasicStroke(LINE_WIDTH, BasicStroke.CAP_ROUND,
            BasicStroke.JOIN_ROUND));
      g2.setColor(LINE_COLOR);
      int x1 = lastPoint.x;
      int y1 = lastPoint.y;
      int x2 = thisPoint.x;
      int y2 = thisPoint.y;
      g2.drawLine(x1, y1, x2, y2);
      g2.dispose();
   }

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

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(bImage, 0, 0, null);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

      if (thisPoint != null) {
         drawThisPoint(g2);
      }
   }

   private void drawThisPoint(Graphics2D g2) {
      int x = thisPoint.x - THIS_PT_WIDTH / 2;
      int y = thisPoint.y - THIS_PT_HEIGHT / 2;
      Graphics2D g2b = (Graphics2D) g2.create();
      g2b.setStroke(new BasicStroke(THIS_PT_STROKE_WIDTH));
      g2b.setColor(THIS_PT_FILL_COLOR);
      g2b.fillOval(x, y, THIS_PT_WIDTH, THIS_PT_HEIGHT);
      g2b.setColor(THIS_PT_BORDER_COLOR);
      g2b.drawOval(x, y, THIS_PT_WIDTH, THIS_PT_HEIGHT);
      g2b.dispose();
   }

   private double function(double x) {
      return 24 * Math.sin(x / 12.0) * Math.sin(x);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("BufferedImage Example");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new BufferedImageEg());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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