Java Swing animation looks messy How to make it look pro?
Update: semiconplex animation swing timer = trainwreck The ultimate source of the problem is the Java timer, both swing and utility versions They are unreliable, especially when comparing performance between operating systems By implementing a running thread, the program runs smoothly on all systems http://zetcode.com/tutorials/javagamestutorial/animation/. In addition, the toolkit getDefaultToolkit(). Adding sync () to the paintcomponent () method is obviously helpful
I wrote some in AWT The code for smooth animation in applet (but flashing), and then I refactor it into Java swing Now it won't blink, but it looks shocking I made a mistake with the timer, but it won't work Any tips or suggestions on smooth animation swing components will be appreciated
import java.util.Random; import java.util.ArrayList; import java.awt.event.; import java.awt.; import javax.swing.*; ////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////public class Ball extends JApplet{
public static void main(String[] args) { SwingUtilities.invokelater(new Runnable() { public void run() { JFrame frame = new JFrame(); frame.setTitle("And so the ball rolls"); frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE); initContainer(frame); frame.pack(); frame.setVisible(true); } }); } public static void initContainer(Container container){ GraphicsPanel graphicsPanel = new GraphicsPanel(); MainPanel mainPanel = new MainPanel(graphicsPanel); container.add(mainPanel); graphicsPanel.startTimer(); } @Override public void init(){ initContainer(this); }
}
////////////////////////////////////////////////// /////////////////////
////////////////////////////////////////////////// ////////////////////
MainPanel类扩展了JPanel {
JLabel label = new JLabel(“Particles”);
GraphicsPanel gPanel;public MainPanel(GraphicsPanel gPanel){ this.gPanel = gPanel; add(gPanel); add(label); }
}
////////////////////////////////////////////////// /////////////////////
////////////////////////////////////////////////// ////////////////////
GraphicsPanel类扩展了JPanel实现的MouseListener {private ArrayList<Particle> ballArr = new ArrayList<Particle>(); private String state="s"; //"s"=spiral,"p"=particle private int speed=10; //~20 Hz private Timer timer; public GraphicsPanel(){ System.out.println("echo from gpanel"); setPreferredSize(new Dimension(500,500)); timer = new Timer(speed,new TimerListener()); addMouseListener(this); } public void startTimer(){ timer.start(); } @Override public void paintComponent(Graphics g){ super.paintComponent(g); for (Particle b: ballArr){ g.setColor(b.getColor()); g.fillOval(b.getXCoor(),b.getYCoor(),b.getTheSize(),b.getTheSize()); } } public void mousePressed(MouseEvent e) { ballArr.add(new Particle(e.getX(),e.getY(),state)); } public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseClicked(MouseEvent e) {} class TimerListener implements ActionListener { public void actionPerformed(ActionEvent e){ for (Particle b: ballArr) b.move(); setBackground(Color.WHITE); repaint(); } }
}
////////////////////////////////////////////////// ////////////////////////
////////////////////////////////////////////////// ////////////////////////
粒子类
{
private static int instanceCount; {{instanceCount;}}
private int z = 11,t = 1,u = 1;
private int [] RGB = new int [3];
private int [] randomizeColor = new int [3];
私人双半径,θ;
private int x,y,centerX,centerY,size,spiralDirection = 1,
ballSizeLowerBound,ballSizeUpperBound,
radiusLowerBound,radiusUpperBound,
mouseInputX,mouseInputY,
radiusXMultiplier,radiusYMultiplier;
私人色彩;
私人字符串状态;
随机随机random = new Random();
////////////////////////////////////////////////// /////////////////////////
public Particle(int x,int y,int centerX,int centerY,int radius,
int theta,int size,Color color){
this.x = X; this.y = Y; this.centerX =的centerX; this.centerY = centerY;
this.radius =半径; this.theta =峰; this.size =大小; this.color =颜色;
}public Particle(int mouseInputX,int mouseInputY,String state){
this.mouseInputX = mouseInputX;
this.mouseInputY = mouseInputY;
this.state =状态;
//随机化颜色
RGB [0] = random.nextInt(252);
RGB [1] = random.nextInt(252);
RGB [2] = random.nextInt(252);
randomizeColor [0] = 1 random.nextInt(3);
randomizeColor [0] = 1 random.nextInt(3);
randomizeColor [0] = 1 random.nextInt(3);
的centerX = mouseInputX;
centerY = mouseInputY;
if(state.equals(“s”)){//设置螺旋状态
ballSizeLowerBound = 5;
ballSizeUpperBound = 18;
radiusLowerBound = 0;
radiusUpperBound = 50;
radiusXMultiplier = 1;
radiusYMultiplier = 1;
}
if(state.equals(“p”)){//设置粒子状态
ballSizeLowerBound = 15;
ballSizeUpperBound = 20 random.nextInt(15);
radiusLowerBound = 5;
radiusUpperBound = 15 random.nextInt(34);
radiusXMultiplier = 1 random.nextInt(3);
radiusYMultiplier = 1 random.nextInt(3);
}size = ballSizeUpperBound-1; //球大小
radius = radiusUpperBound-1;if(instanceCount%2 == 0)//交替的螺旋方向
spiralDirection = -spiralDirection;
}
////////////////////////////////////////////////// /////////////////////////
public int getXCoor(){return centerX x * spiralDirection;}
public int getYCoor(){return centerY y;}
public int getTheSize(){return size;}
public Color getColor(){return color;}
////////////////////////////////////////////////// ////////////////////////
void move(){// spiral:dr / dt在边界变化
if(radius> radiusUpperBound || radius< radiusLowerBound)
u = -u;//螺旋形式公式:参数方程式
极性方程半径= theta
x =(int)(radius * radiusXMultiplier * Math.cos(theta));
y =(int)(radius * radiusYMultiplier * Math.sin(theta));radius = 0.1 * u;
theta = 0.1;//球尺寸公式
if(size == ballSizeUpperBound || size == ballSizeLowerBound)
t = -t;
size = t;//球颜色变化
for(int i = 0; i
if(RGB [i]> = 250 || RGB [i]< = 4)
randomizeColor [i] = -randomizeColor [i];RGB [0] = randomizeColor [0];
RGB [1] = randomizeColor [1];
RGB [2] = randomizeColor [2];
color = new Color(RGB [0],RGB [1],RGB [2]);
}}
public static void main(String[] args) {
SwingUtilities.invokelater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setTitle("And so the ball rolls");
frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
initContainer(frame);
frame.pack();
frame.setVisible(true);
}
});
}
public static void initContainer(Container container){GraphicsPanel graphicsPanel = new GraphicsPanel();
MainPanel mainPanel = new MainPanel(graphicsPanel);
container.add(mainPanel);
graphicsPanel.startTimer();}
@Override
public void init(){
initContainer(this);
}public MainPanel(GraphicsPanel gPanel){
this.gPanel = gPanel;
add(gPanel);
add(label);
}private ArrayList<Particle> ballArr = new ArrayList<Particle>();
private String state="s"; //"s"=spiral,state));
}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e) {}class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e){
for (Particle b: ballArr)
b.move();
setBackground(Color.WHITE);
repaint();}
}Solution
Do not set the constant interval timer Set timer once in Timer - in handler
>Get the current time (saved in framestarttime) > be your frame > set the timer to: interval - (newcurrenttime - framestarttime)
It should be more fluent. If you want to be really pro (and stay in Java), I think you must consider JavaFX