Problem z płynnością animacji

0

Dzieńdoberek, po dość długim czasie wróciłem do programowania i na rozgrzewkę postanowiłem napisać sobie program, w którym kółko lata od ściany do ściany i się odbija. Wszystko ładnie, pięknie, ale niepłynnie. Bawiłem się delayem i "długością skoku" na jeden raz, ale nie pomogło. Zauważyłem dziwną rzecz - kiedy latam kursorem nad okienkiem, to działa płynnie, a kiedy tylko przestanę albo z niego zjadę, to kółko znowu zaczyna skakać. Pracuję na Ubuntu 12.04 LTS.

Klasa App:

import javax.swing.*;

public class App extends JFrame {

	
	public App() {
		setSize(800, 600);
		setVisible(true);
		setLocationRelativeTo(null);
		Anim anim = new Anim();
		add(anim);
		anim.StartAnim();
	}
	
	public static void main(String [] args) {
		new App();
	}
	
}

Klasa Anim:

import java.awt.*;
import javax.swing.*;
public class Anim extends JPanel {
	
	int x = 30, y = 30, dx = 1, dy = 3, delay = 10;
	
	public void StartAnim() {
		while(true) {
			if(x + 30 > getWidth() || x < 0)
				dx =- dx;
			if(y + 30 > getHeight() || y < 0)
				dy =- dy;
			
			x+=dx;
			y+=dy;
			
			repaint();
			try{ 
				Thread.sleep(delay);
			} catch(InterruptedException e) { System.out.println("IE e!"); }
		}
	}
	
	
	
	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setColor(Color.red);
		g2d.fillOval(x, y, 30, 30);
	}
}
1

Welcome to java, and have a nice day!

0

Robisz sleep() w wątku EDT, czyli wątku obsługi zdarzeń, dlatego aplikacja 'zamarza'. Wszystkie długotrwałe czynności powinny być wykonywane w osobnych wątkach. A w sytuacji takiej jak Twoja najlepiej będzie wykorzystać Timer

0

Chodzi o coś takiego?

App:

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;

public class App extends JFrame {
	
	
	
	private static class Anim extends JPanel {		
		int x = 50, y = 50, dx = 5, dy = 3;
		
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;
			if(x + 50 > getWidth() || x < 0)
				dx=-dx;
			if(y + 50 > getHeight() || y < 0)
				dy=-dy;
			
			x+=dx;
			y+=dy;
			g2d.fillOval(x, y, 50, 50);
		}
	}
	public App()
	{
		setSize(500, 400);
		setLocationRelativeTo(null);
		Anim panel = new Anim();
		add(panel);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		new Watek(panel);
	}

	public static void main(String[] args) {
		new App();
	}
	
}

Watek:

import java.awt.Component;

public class Watek implements Runnable {
	private final Component c;
	int delay = 10;
		public Watek(Component c) {
			this.c = c;
			(new Thread(this, "F")).start();
		}
	
	public void run() {
		while(true) {
			c.repaint();
			try {
				Thread.sleep(delay);
			} catch (Exception e) {
				System.out.println("Exception!");
			}
		}
	}
}
0

Raczej o coś takiego:

        public void StartAnim() {
            ActionListener task = new ActionListener()
            {
                public void actionPerformed(ActionEvent ae)
                {
                        if(x + 30 > getWidth() || x < 0)
                                dx =- dx;
                        if(y + 30 > getHeight() || y < 0)
                                dy =- dy;
 
                        x+=dx;
                        y+=dy;
 
                        repaint();              
                }
            };
            Timer timer = new Timer(delay,task);
            timer.start();
        }
0

Bogdans, zrobiłem tak, by wykorzystać Twoją metodę i działa tak jak poprzednio :/
Może to nie jest wina samego programu? Bo jak pisałem na Windowsie to takich dziwactw z kursorem nie miałem.

0

A jaką masz Javę? po linuksach pęta się jakaś java nie oraclowska, Swing działa na niej źle.

0

java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

0

Wygląda na Oracle.

0

Jak na chwilę obecną wygląda Twój kod? Porównaj go z tym poniżej, który u mnie na Ubuntu zachowuje się jak należy.

package app;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class App {

    public static void main(String[] args) {
        new App();
    }
    private JFrame frame;
    private PaintingPanel panel;

    public App() {
        frame = new JFrame();
        frame.setSize(500, 500);

        panel = new PaintingPanel();
        frame.add(panel);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                frame.setVisible(true);
            }
        });
        Timer t = new Timer(10, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.update();
            }
        });
        t.start();
    }

    class PaintingPanel extends JPanel {

        int x = 50, y = 50, dx = 5, dy = 3;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;

            g2d.fillOval(x, y, 50, 50);
        }

        public void update() {
            if (x + 50 > getWidth() || x < 0) {
                dx = -dx;
            }
            if (y + 50 > getHeight() || y < 0) {
                dy = -dy;
            }

            x += dx;
            y += dy;
            repaint();
        }
    }
}
2

dodaj do metody paintComponent:
Toolkit.getDefaultToolkit().sync();
Podobno rozwiązuje problemy z płynnością animacji na linuxie - profilaktycznie i ja dodałem ją u siebie, choć nie miałem żadnych problemów - arch 64 bit

0

@hcubyc, bardzo prawdopodobne. Fragment dokumentacji tej metody:

Synchronizes this toolkit's graphics state. Some window systems may do buffering of graphics events.
This method ensures that the display is up-to-date. It is useful for animation.

0

hcubyc, Twój pomysł się sprawdził, dzięki :D Airborn, Bogdans, dzięki za wskazanie innych problemów z moim programem, jesteście wielcy :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1