停止闪烁的摆动,当我重新绘制太多 [英] Stop flickering in swing when i repaint too much
问题描述
我使用tilemap制作RPG。要生成瓷砖地图i循环通过一个2维数组,但这意味着,当我重新绘制我必须这样做每次。如果我重新绘制太多的屏幕闪烁,我怎么能阻止这个。
package sexyCyborgFromAnOtherDimension;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
@SuppressWarnings(serial)
public class Game extends JPanel
{
KeyLis listener;
int mapX = 20;
int mapY = 20;
boolean up = false;
boolean down = false;
boolean right = false;
boolean left = false;
String [] [] map;
public Game()
{
super();
try
{
map = load(/ maps / map1.txt);
}
catch(IOException e)
{
// TODO自动生成的catch块
e.printStackTrace();
}
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
定时器timer =新的Timer();
TimerTask task = new TimerTask()
{
@Override
public void run()
{
if(up)
{
mapY ++;
repaint();
}
if(down)
{
mapY--;
repaint();
}
if(right)
{
mapX--;
repaint();
}
if(left)
{
mapX ++;
repaint();
}
}
};
timer.scheduleAtFixedRate(task,0,10);
}
public void paint(Graphics g)
{
super.paintComponent(g);
setDoubleBuffered(true);
Graphics2D g2 =(Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
for(int x = 0; x {
for(int y = 0; y< map [x] .length; y ++)
{
switch(map [x] [y])
{
case0:
g.setColor(Color.GREEN);
break;
case1:
g.setColor(Color.GRAY);
break;
}
g.fillRect(y * 20 + mapX,x * 20 + mapY,20,20);
}
}
g.setColor(Color.BLACK);
g.fillRect(400,400,20,20);
}
String [] [] load(String file)throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(getClass()。getResourceAsStream )));
int lines = 1;
int length = br.readLine()。split().length;
while(br.readLine()!= null)lines ++;
br.close();
BufferedReader br1 = new BufferedReader(new InputStreamReader(getClass()。getResourceAsStream(file)));
String [] [] map = new String [lines] [length];
for(int i = 0; i< lines; i ++)
{
String line = br1.readLine();
String [] parts = line.split();
for(int y = 0; y< length; y ++)
{
map [i] [y] = parts [y]
}
}
br1.close();
return map;
}
private class KeyLis extends KeyAdapter
{
@Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
}
}
@Override
public void keyReleased(KeyEvent e)
{
switch(e.getKeyCode())
{
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
}
}
}
}
c $ c>即使延迟10 ms,也会移除所有闪烁。
/ p>
首先。你可能最好使用 javax.swing.Timer
而不是 java.util.Timer
,这将至少允许
其次,10毫秒是缩短一段时间,认真的,你不需要100fps,60fps约为17毫秒,我通常对于25fps使用40毫秒。这可能给予EDT一些喘息的空间来实际回应重绘请求。
第三,你应该使用 paintComponent
而不是 paint
。在调用链中保证是双缓冲的
第四,你应该避免调用任何可能重新安排重绘的方法
(如 setDoubleBuffered
例如,在构造函数中,如果必须,但是Swing组件默认是双缓冲的)
第五,在可能的情况下,将所有静态或缓慢变化的内容绘制到后台缓冲区并进行绘制。这将增加 paint
可以工作的速度,因为它不会卡在许多小循环中。
您可以参阅在AWT和Swing中绘画
-
< Swing动画运行极慢 - 能够从500个元素向上一次可在屏幕上移动4500个元素 - - Java弹跳球
- 如何使线条动画更流畅?
- 图片未载入
因为kleo恐吓我这也是一个好主意),您还应该查看如何使用键绑定,这将解决您的焦点问题与 KeyListener
I am making an RPG with a tilemap. To generate the tilemap i loop through a 2 dimensional array but that means that when I repaint I have to do that each time. If I repaint too much the screen flickers how could I stop this.
package sexyCyborgFromAnOtherDimension;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Game extends JPanel
{
KeyLis listener;
int mapX = 20;
int mapY = 20;
boolean up = false;
boolean down = false;
boolean right = false;
boolean left = false;
String[][] map;
public Game()
{
super();
try
{
map = load("/maps/map1.txt");
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
listener = new KeyLis();
this.setFocusable(true);
this.requestFocus();
this.addKeyListener(listener);
Timer timer = new Timer();
TimerTask task = new TimerTask()
{
@Override
public void run()
{
if(up)
{
mapY++;
repaint();
}
if(down)
{
mapY--;
repaint();
}
if(right)
{
mapX--;
repaint();
}
if(left)
{
mapX++;
repaint();
}
}
};
timer.scheduleAtFixedRate(task, 0, 10);
}
public void paint(Graphics g)
{
super.paintComponent(g);
setDoubleBuffered(true);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int x = 0; x < map.length; x++)
{
for (int y = 0; y < map[x].length; y++)
{
switch(map[x][y])
{
case "0":
g.setColor(Color.GREEN);
break;
case "1":
g.setColor(Color.GRAY);
break;
}
g.fillRect(y*20+mapX, x*20+mapY, 20, 20);
}
}
g.setColor(Color.BLACK);
g.fillRect(400, 400, 20, 20);
}
String[][] load(String file) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(file)));
int lines = 1;
int length = br.readLine().split(" ").length;
while (br.readLine() != null) lines++;
br.close();
BufferedReader br1 = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(file)));
String[][] map = new String[lines][length];
for (int i = 0; i < lines; i++)
{
String line = br1.readLine();
String[] parts = line.split(" ");
for (int y = 0; y < length; y++)
{
map[i][y] = parts[y];
}
}
br1.close();
return map;
}
private class KeyLis extends KeyAdapter
{
@Override
public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
up = true;
break;
case KeyEvent.VK_DOWN:
down = true;
break;
case KeyEvent.VK_LEFT:
left = true;
break;
case KeyEvent.VK_RIGHT:
right = true;
break;
}
}
@Override
public void keyReleased(KeyEvent e)
{
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
up = false;
break;
case KeyEvent.VK_DOWN:
down = false;
break;
case KeyEvent.VK_LEFT:
left = false;
break;
case KeyEvent.VK_RIGHT:
right = false;
break;
}
}
}
}
Thank you for your help
Edit
Using javax.swing.Timer
removes all flickering even with a 10 ms delay.
A number of small things jump out at me.
Firstly. You might be better using javax.swing.Timer
instead of java.util.Timer
, this will at least allow the events to flow a little better.
Secondly, 10 milliseconds is to short a time period, seriously, you don't need 100fps, 60fps is about 17 milliseconds, I normally use 40 milliseconds for 25fps. This might give the EDT some breathing room to actually respond to the repaint requests.
Thirdly, you should be using paintComponent
instead of paint
. It's low enough in the call chain to guaranteed to be double buffered
Fourthly, you should avoid calling any method that might reschedule a repaint
(like setDoubleBuffered
for example, to this in the constructor if you must, but, Swing components are double buffered by default)
Fifthly, where possible, paint all "static" or slow changing content to a backing buffer and paint that instead. This will increase the speed at which paint
can work as it doesn't get stuck in a lot of small loops.
You may want to take a look at Painting in AWT and Swing for more details about the paint process
Some additional examples...
- Swing animation running extremely slow - was able to go from 500 elements up to 4500 elements moving on the screen at one time - talks about resource management as well
- Java Bouncing Ball
- How to make line animation smoother?
- the images are not loading
And because kleo scares me (and it's also a good idea), you should also take a look at How to use Key Bindings, which will solve your focus issues with the KeyListener
这篇关于停止闪烁的摆动,当我重新绘制太多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!