【问题标题】:Graphics flashing in JAppletJApplet 中的图形闪烁
【发布时间】:2016-06-21 20:29:54
【问题描述】:

我知道这已经被问过很多次了,但是每次我访问问题线程并执行提出的解决方案时,它仍然对我不起作用。

所以在我造成任何混乱之前,我遇到的问题是我绘制的屏幕一直在闪烁,这是因为每次我绘制屏幕时,我都会用一个完全白色填充的矩形来清除屏幕,我绘制的东西矩形会闪烁。

这是我的代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;
import javax.swing.Timer.*;

/**
  *
  * beschrijving
  *
  * @version 1.0 van 16-6-2016
  * @author 
  */

public class shadows3 extends JApplet implements ActionListener{
  // Begin variabelen
  int[] loc = new int[2];
  int[][] wall = new int[10][8];
  // Einde variabelen

  public void init() {
    Container cp = getContentPane();
    cp.setLayout(null);
    cp.setBounds(0, 0, 600, 600);
    // Begin componenten
    for (int a=0; a<10; a++) {
      int tempx = (int) (Math.random()*20)*30;
      int tempy = (int) (Math.random()*20)*30;
      wall[a][0] = tempx;
      wall[a][1] = tempy;
      wall[a][2] = tempx+30;
      wall[a][3] = tempy;
      wall[a][4] = tempx+30;
      wall[a][5] = tempy+30;
      wall[a][6] = tempx;
      wall[a][7] = tempy+30;
    } // end of for

    loc[0] = 300;
    loc[1] = 300;

    Timer step = new Timer(20, this);
    step.start();
    // Einde componenten

  } // end of init
  private int length(int x1, int y1, int x2, int y2) {
    double distance = Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
    return (int) distance;
  }

  // Begin eventmethoden

  public void paint (Graphics g){
    g.setColor(Color.WHITE);
    g.fillRect(0,0,600,600);

    int[] xpoints = new int[8];
    int[] ypoints = new int[8];
    int[] list = new int[3];
    for (int a=0; a<5; a++) {
      for (int b=0; b<4; b++) {
        if (length(wall[a][b*2],wall[a][b*2+1],loc[0],loc[1])==Math.max(Math.max(length(wall[a][0],wall[a][1],loc[0],loc[1]),
        length(wall[a][2],wall[a][3],loc[0],loc[1])),
        Math.max(length(wall[a][4],wall[a][5],loc[0],loc[1]),
        length(wall[a][6],wall[a][7],loc[0],loc[1])))) {
          int temp = b;
          for (int c=0; c<3; c++) {
            temp += 1;
            if (temp == 4) {
              temp = 0;
            } // end of if
            list[c] = temp;
          } // end of for
        } // end of if
      } // end of for
      xpoints[0] = wall[a][list[0]*2  ];
      ypoints[0] = wall[a][list[0]*2+1];

      xpoints[1] = wall[a][list[1]*2  ];
      ypoints[1] = wall[a][list[1]*2+1];

      xpoints[2] = wall[a][list[2]*2  ];
      ypoints[2] = wall[a][list[2]*2+1];

      xpoints[3] = wall[a][list[2]*2  ]+(wall[a][list[2]*2  ]-loc[0])*10000;
      ypoints[3] = wall[a][list[2]*2+1]+(wall[a][list[2]*2+1]-loc[1])*10000;

      xpoints[4] = wall[a][list[0]*2  ]+(wall[a][list[0]*2  ]-loc[0])*10000;
      ypoints[4] = wall[a][list[0]*2+1]+(wall[a][list[0]*2+1]-loc[1])*10000;

      g.setColor(Color.BLACK);
      g.fillPolygon(xpoints, ypoints, 5);
      //g.fillRect(wall[a][0],wall[a][1],30,30);
    } // end of for
  }

  //@Override
  public void actionPerformed(ActionEvent e){
    loc[0] += 4;
    loc[1] += 2;

    repaint();
  }
  // Einde eventmethoden

} // end of class shadows3

如果您想知道我要创建什么,它是某种实时阴影引擎,它相当慢,但它只是一个有趣的项目,虽然对于我的许多项目来说,屏幕闪烁是一个真正的问题。

非常感谢!

【问题讨论】:

标签: java swing japplet


【解决方案1】:

因为您应该 migrating 进入无插件环境,请考虑通过 部署的 hybrid。下面的示例在 JPanel 中显示您的内容,默认情况下是双缓冲的。特别是,

测试:

$ javac ShadowApplet.java ; appletviewer ShadowApplet.java

代码:

//<applet code="ShadowApplet.class" width=600 height=600></applet>
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 * @see https://stackoverflow.com/a/37958844/230513
 */
public class ShadowApplet extends JApplet {

    private static final Random R = new Random(42);

    @Override
    public void init() {
        EventQueue.invokeLater(() -> {
            add(new ShadowPanel());
        });
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new ShadowApplet()::display);
    }

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new ShadowPanel());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class ShadowPanel extends JPanel implements ActionListener {

        int[] loc = new int[2];
        int[][] wall = new int[10][8];

        public ShadowPanel() {
            this.setLayout(null);
            this.setBackground(Color.WHITE);
            for (int a = 0; a < 10; a++) {
                int tempx = R.nextInt(20) * 30;
                int tempy = R.nextInt(20) * 30;
                wall[a][0] = tempx;
                wall[a][1] = tempy;
                wall[a][2] = tempx + 30;
                wall[a][3] = tempy;
                wall[a][4] = tempx + 30;
                wall[a][5] = tempy + 30;
                wall[a][6] = tempx;
                wall[a][7] = tempy + 30;
            }
            loc[0] = 300;
            loc[1] = 300;
            Timer step = new Timer(20, this);
            step.start();
        }

        private int length(int x1, int y1, int x2, int y2) {
            double distance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
            return (int) distance;
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            int[] xpoints = new int[8];
            int[] ypoints = new int[8];
            int[] list = new int[3];
            for (int a = 0; a < 5; a++) {
                for (int b = 0; b < 4; b++) {
                    if (length(wall[a][b * 2], wall[a][b * 2 + 1], loc[0],
                        loc[1]) == Math.max(Math.max(length(wall[a][0], wall[a][1], loc[0], loc[1]),
                            length(wall[a][2], wall[a][3], loc[0], loc[1])),
                            Math.max(length(wall[a][4], wall[a][5], loc[0], loc[1]),
                                length(wall[a][6], wall[a][7], loc[0], loc[1])))) {
                        int temp = b;
                        for (int c = 0; c < 3; c++) {
                            temp += 1;
                            if (temp == 4) {
                                temp = 0;
                            }
                            list[c] = temp;
                        }
                    }
                }
                xpoints[0] = wall[a][list[0] * 2];
                ypoints[0] = wall[a][list[0] * 2 + 1];

                xpoints[1] = wall[a][list[1] * 2];
                ypoints[1] = wall[a][list[1] * 2 + 1];

                xpoints[2] = wall[a][list[2] * 2];
                ypoints[2] = wall[a][list[2] * 2 + 1];

                xpoints[3] = wall[a][list[2] * 2] + (wall[a][list[2] * 2] - loc[0]) * 10000;
                ypoints[3] = wall[a][list[2] * 2 + 1] + (wall[a][list[2] * 2 + 1] - loc[1]) * 10000;

                xpoints[4] = wall[a][list[0] * 2] + (wall[a][list[0] * 2] - loc[0]) * 10000;
                ypoints[4] = wall[a][list[0] * 2 + 1] + (wall[a][list[0] * 2 + 1] - loc[1]) * 10000;

                g.setColor(Color.BLACK);
                g.fillPolygon(xpoints, ypoints, 5);
                g.fillRect(wall[a][0], wall[a][1], 30, 30);
            }
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            loc[0] += 4;
            loc[1] += 2;
            repaint();
        }

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

【讨论】:

  • 谢谢,我一定会看看的
【解决方案2】:

您需要创建一个单独的图像来绘制所有内容:

im=createImage(getWidth(), getHeight());

在初始化中。

然后在你的画中:

Graphics g2=im.getGraphics();
g2.setColor(Color.WHITE);
g2.fillRect(0,0,600,600);

并继续将所有 g 命令替换为 g2:

g2.setColor(Color.BLACK);
g2.fillPolygon(xpoints, ypoints, 5);

然后你在 g 上绘制图像:

g.drawImage(im, 0, 0, this);

你有一个更新方法:

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

【讨论】:

    猜你喜欢
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 2013-01-09
    • 1970-01-01
    • 2014-08-12
    • 2016-06-24
    相关资源
    最近更新 更多