2016-09-27 3 views
1

J'essaie de faire un peu de base Java, et j'ai mon cadre avec une forme en elle. Il utilise une classe JComponent pour dessiner la forme, l'animation étant déclenchée sur un clic de bouton en haut.Repaint ne se produira pas jusqu'à ce que la boucle for a échappé, avec seulement deux images

le code de composant est tout cela ajouté à la DPanel

public void paintComponent(Graphics g){  
    Dimension dim = getSize();  
    g.setColor(Color.GREEN); 
    g.fillOval(margin, 150, 100, 100); 
    super.paintComponent(g); 
} 

L'animation est tout fait à l'intérieur d'une boucle, qui vient modifie la marge de gauche de sorte que le cercle se déplace vers la droite;

int getMarg = cc.getMargin(); 
      for(int i = 1;i < 20;i++){ 
       getMarg = cc.getMargin(); 
       cc.setMargin(getMarg + 1);    
       reValidate(); 
       System.out.println(i); 

Mais il ne semble pas se déplacer jusqu'à la fin de la boucle, se déplaçant de 20 pixels à la fois. J'avais auparavant une fonction de sommeil mais cela semblait inutile quand ça ne l'animait pas.

Un aperçu? À votre santé.

Le code entier pour toute personne intéressée, en désordre et en grande partie juste pour obtenir le style:

class Main extends JFrame{ 

public JPanel panel = new JPanel(); 
JButton button1 = new JButton("Move Right"); 

CreateComps cc = new CreateComps(); 

Main(){ 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    initUI(); 
} 

void initUI(){ 
    setSize(800,800); 
    setBackground(Color.GRAY); 
    setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS)); 

    JPanel topBar = new JPanel(); 
    topBar.setPreferredSize(new Dimension(800,30)); 
    topBar.setMaximumSize(new Dimension(800,30)); 
    topBar.setLayout(new BorderLayout()); 
    topBar.add(button1, BorderLayout.WEST); 
    topBar.setBackground(Color.GRAY); 

    JPanel container = new JPanel(); 
    container.setLayout(new GridBagLayout()); 
    container.setBackground(Color.DARK_GRAY); 

    panel.setPreferredSize(new Dimension(600,500)); 
    panel.setMinimumSize(new Dimension(600,500)); 
    panel.setBackground(Color.WHITE); 
    panel.setLayout(new BorderLayout()); 
    panel.add(cc, BorderLayout.CENTER); 

    add(topBar); 
    add(container); 
    container.add(panel); 

    Listener listen = new Listener(); 
    button1.addActionListener(listen); 

    setVisible(true); 
} 

public void reValidate(){ 
    panel.revalidate(); 
    panel.repaint(); 
} 

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

class Listener implements ActionListener{ 
    @Override 
    public void actionPerformed(ActionEvent e) { 

     System.out.println("Listening.."); 
     if(e.getSource().equals(button1)){ 
      int getMarg = cc.getMargin(); 
      for(int i = 1;i < 20;i++){ 
       getMarg = cc.getMargin(); 
       cc.setMargin(getMarg + 1);    
       reValidate(); 
       System.out.println(i); 
      } 
     }      
    } 
} 



} 

class CreateComps extends JComponent{ 

int margin = 10;   
public void setMargin(int marg){ 
    margin = marg; 
} 
public int getMargin(){ 
    return margin; 
} 
@Override 
public Dimension getPreferredSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
@Override 
public Dimension getMaximumSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
@Override 
public Dimension getMinimumSize(){ 
    return new Dimension(new Dimension(200,200)); 
} 
public void paintComponent(Graphics g){  
    Dimension dim = getSize();  
    g.setColor(Color.GREEN); 
    g.fillOval(margin, 150, 100, 100); 
    super.paintComponent(g); 
} 

}

Répondre

0

Sans pauses, vous empilez les appels à revalidate et ne verrez rien d'autre que le résultat du dernier appel.

La fonction de veille que vous aviez précédemment a probablement été appelée sur le Event Dispatch Thread, ce qui n'est pas bon du tout, puisque vous bloquez l'ensemble des mises à jour d'envoi d'événement et de GUI.

Tenir compte soit à l'aide sleep appels sur un autre Thread:

@Override 
public void actionPerformed(final ActionEvent e) { 

    System.out.println("Listening.."); 
    if (e.getSource().equals(button1)) { 
     new Thread() { 
      @Override 
      public void run() { 
       int getMarg = cc.getMargin(); 
       for (int i = 1; i < 20; i++) { 
        getMarg = cc.getMargin(); 
        cc.setMargin(getMarg + 1); 
        reValidate(); 
        System.out.println(i); 

        try { 
         Thread.sleep(50); 
        } catch (Throwable e) { 
        } 

       } 
      } 
     }.start(); 

    } 

} 

Ou vous pouvez également utiliser simplement un Timer, ce qui est idéal pour ce travail.

+1

Merci beaucoup, marqué comme réponse. acclamations :) –

+0

Alors que cela éclaire le cœur du problème (boucle serrée/sommeil sur l'EDT), je ne peux pas remettre en cause une réponse que tant de mauvaises pratiques dans un si petit morceau de code. Pour une fois, presque toutes les classes de Swing ont "Swing n'est pas thread safe". N'appelez pas 'getMargin()' et 'setMargin()' etc. à partir de threads non-EDT. Et pourquoi voudriez-vous créer un nouveau thread entier quand vous avez la classe Swing 'Timer' commode qui exécutera votre' Runnable' sur le EDT directement sans avoir besoin de dormir? – Ordous