2017-10-05 6 views
2

Eh bien, je suis ce tutorial pour créer ma propre animation et quand je l'exécute tout fonctionne bien sur Windows mais dans Ubuntu 17.04 l'animation est lisse seulement si la souris se déplace sur l'application fenêtre. Si cela ne fonctionne pas comme "en va-et-vient" (je pense que c'est une bonne traduction). voici mon code:Rend mon animation java swing plus lisse sous Linux

import javax.swing.Box; 
import javax.swing.BoxLayout; 
import java.awt.Color; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Window extends JFrame { 

private Panel pan = new Panel(); 
private JButton play = new JButton("play"); 
private JButton pause = new JButton("pause"); 

public Window(String titre) { 

    this.setTitle(titre); 
    this.setSize(900, 600); 
    this.setLocationRelativeTo(null); 
    this.setAlwaysOnTop(true); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    Box b1 = Box.createHorizontalBox(); 
    b1.add(play); 
    b1.add(pause); 

    Box b2 = Box.createVerticalBox(); 
    b2.add(b1); 
    this.setContentPane(pan); 
    this.getContentPane().add(b2); 
    this.setVisible(true); 
    this.go(); 

} 

private void go() { 
    // Les coordonnées de départ de notre rond 
    int x = pan.getPosX(), y = pan.getPosY(); 
    // Le booléen pour savoir si l'on recule ou non sur l'axe x 
    boolean backX = false; 
    // Le booléen pour savoir si l'on recule ou non sur l'axe y 
    boolean backY = false; 

    // Dans cet exemple, j'utilise une boucle while 
    // Vous verrez qu'elle fonctionne très bien 
    while (true) { 
     // Si la coordonnée x est inférieure à 1, on avance 
     if (x < 1) 
      backX = false; 

     // Si la coordonnée x est supérieure à la taille du Panneau moins la taille du 
     // rond, on recule 
     if (x > pan.getWidth() - 50) 
      backX = true; 

     // Idem pour l'axe y 
     if (y < 1) 
      backY = false; 
     if (y > pan.getHeight() - 50) 
      backY = true; 

     // Si on avance, on incrémente la coordonnée 
     // backX est un booléen, donc !backX revient à écrire 
     // if (backX == false) 
     if (!backX) 
      pan.setPosX(++x); 

     // Sinon, on décrémente 
     else 
      pan.setPosX(--x); 

     // Idem pour l'axe Y 
     if (!backY) 
      pan.setPosY(++y); 
     else 
      pan.setPosY(--y); 

     // On redessine notre Panneau 
     pan.repaint(); 

     // Comme on dit : la pause s'impose ! Ici, trois millièmes de seconde 
     try { 
      Thread.sleep(2); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

} 

classe de seconde:

import javax.swing.JPanel; 

import java.awt.Color; 
import java.awt.Font; 
import java.awt.GradientPaint; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 

public class Panel extends JPanel { 

private int posX = -50; 
private int posY = -50; 

public void paintComponent(Graphics g) { 
    g.setColor(Color.WHITE); 
    g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
    g.setColor(Color.red); 
    g.fillOval(posX, posY, 50, 50); 
} 

public int getPosX() { 
    return posX; 
} 

public void setPosX(int posX) { 
    this.posX = posX; 
} 

public int getPosY() { 
    return posY; 
} 

public void setPosY(int posY) { 
    this.posY = posY; 
} 
} 

et le principal:

import javax.swing.JFrame; 
public class test { 
public static void main(String [] args) { 
    Window window = new Window("Animation"); 

} 

} 

Nous vous remercions à l'avance à toute personne qui peut être en mesure de me donner quelques idées :)

+0

C'est probablement un économiseur de ressources Linux a, si la fenêtre n'est pas active, pourquoi gaspiller des ressources qui le dessinent? – Dinh

+0

Eh bien, je mets une haute ressource avec le système de surveillance et ça fait la même chose. De plus quand je joue à minecraft cela fonctionne bien même si ma souris n'est pas au-dessus de la fenêtre haha ​​ –

+0

Je serais méfiant que votre méthode 'paintComponent' repose sur des propriétés qui peuvent être modifiées par un autre thread - si vous voulez un meilleur contrôle sur la processus de peinture, vous devriez envisager d'utiliser un 'BufferStrategy' à la place – MadProgrammer

Répondre

2

Essayez d'appeler

Toolkit.getDefaultToolkit(). Sync();

Une fois que vous faites

pan.repaint();

+0

merci ça marche très bien maintenant !! mais pourquoi? –

+0

@DaniSanz C'est une question très vaste, commencez par jeter un coup d'œil sur "[JavaDocs] (https://docs.oracle.com/javase/8/docs/api/java/awt/Toolkit.html#sync--) - * "Cette méthode garantit que l'affichage est à jour. C'est utile pour l'animation. "*, Je vous recommande également de jeter un oeil à [Painting in Swing] (http://www.oracle.com/technetwork/java/painting-140037.html) pour plus de détails sur la façon dont le Le processus de peinture fonctionne réellement – MadProgrammer

+0

Il y a un problème avec la programmation graphique de Linux, ce qui ralentit et ralentit pour une raison ou une autre L'appel prend de précieux temps CPU (beaucoup, en fait), alors utilisez System.getProperty ("os.name ") pour déterminer si vous avez besoin de l'utiliser – Dinh