2016-07-25 1 views
0

J'ai un JLayeredPane personnalisé, et je le repeins dans ma boucle de jeu. Deux JPanels personnalisés sont ajoutés dans JLayeredPane. Ce sont les JPanels de premier plan et d'arrière-plan. Comment puis-je dessiner avec succès mon arrière-plan JPanel une fois, (et repeindre lorsque la fenêtre est redimensionnée ou toute autre raison) pour réduire l'impact sur les ressources du système, tout en continuant à mettre à jour mon premier plan JPanel constamment. Pour réitérer, je ne veux pas repeindre constamment l'arrière-plan JPanel en boucle. Je veux le repeindre seulement quand c'est nécessaire, car le fond ne change pas. et est grand. Dans ma tentative de faire cela, j'ai seulement dessiné l'arrière-plan une fois. Toutefois. l'arrière-plan JPanel n'est tout simplement pas visible. alors que le premier plan JPanel se met à jour normalement. C'est presque comme si le premier plan JPanel peignait sur l'arrière-plan JPanel, même si j'ai les deux JPanels réglés à setOpaque(false)Comment dessiner l'arrière-plan JPanel une fois et mettre au premier plan JPanel constamment?

J'ai fait un mvce qui montre ma tentative de dessiner seulement l'arrière-plan JPanel une fois, tout en mettant à jour le au premier plan JPanel constamment.

Le problème avec mon code est que l'arrière-plan JPanel ne s'affiche pas.

Maintenant. Je sais que si je devais le dessiner constamment, cela montrerait. Mais cela va à l'encontre du but de ce que j'essaie de faire. J'essaye de dessiner seulement une fois, et ai été vu en même temps

Mon code réussit dessine seulement l'arrière-plan JPanel une fois. Le problème est que l'arrière-plan JPanel ne s'affiche pas. Comment puis-je résoudre ce problème

import javax.swing.*; 

import java.awt.*; 
import java.awt.event.*; 

public class Main extends JLayeredPane { 
    static JFrame frame; 
    static Main main; 
    static Dimension screenSize; 
    public Main() {  
     JPanel backPanel = new BackPanel(); 
     JPanel frontPanel = new FrontPanel(); 
     add(backPanel, new Integer(7)); 
     add(frontPanel, new Integer(8)); 

     new Thread(() -> { 
      while (true){ 
       repaint(); 
      } 
     }).start(); 

    } 

    public static void main(String[] args) { 
     screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

     frame = new JFrame("Game"); // Just use the constructor 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     main = new Main(); 
     frame.add(main, BorderLayout.CENTER); 

     frame.pack(); 
     frame.setSize(screenSize); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

    } 
    public class BackPanel extends JPanel{ 
     public boolean drawn = false; 
     public BackPanel(){ 
      setVisible(true); 
      setOpaque(false); 
      setSize(screenSize); 
      JLabel test1 = new JLabel("Test1"); 
      JLabel test2 = new JLabel("Test2"); 
      add(test1); 
      add(test2); 
     } 
     @Override 
     public void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      drawOnce(g); 
     } 
     public void drawOnce(Graphics g){ 
      if (!drawn){ 
       g.setColor(Color.red); 
       g.fillRect(0, 0, screenSize.width, 200); 
       drawn=true; 
      } 

     } 
    } 
    public class FrontPanel extends JPanel{ 

     public FrontPanel(){ 
      setVisible(true); 
      setOpaque(false); 
      setSize(screenSize); 
      JLabel test = new JLabel("Test"); 
      add(test); 
     } 
     @Override 
     public void paintComponent(Graphics g){ 
      super.paintComponent(g); 
      g.setColor(Color.blue); 
      g.fillRect(0+screenSize.width/2, 0, screenSize.width/4, 300); 
     } 
    } 
} 
+0

'pour augmenter FPS' Pourquoi avez-vous besoin d'augmenter la fréquence d'images? Pensez à utiliser un javax.swing.Timer pour avoir un meilleur contrôle sur fps et rafraichir à une fréquence d'image particulière (comme 60fps - en d'autres termes, augmenter le fps n'est pas forcément avantageux) – copeg

+0

@copeg Dans mon projet actuel, j'essaie d'atteindre FPS le plus élevé possible, et continuez de mettre à jour mon jeu à 60 ticks par seconde. J'ai reformulé ma réponse pour dire utiliser moins de ressources système au lieu d'augmenter FPS. – Colourfit

+1

Le système de peinture Swing est conçu pour repeindre si nécessaire - si votre routine de peinture est complexe et que vous souhaitez le faire une seule fois, envisagez de dessiner une image BufferedImage la première fois, puis dessinez l'image au JPanel – copeg

Répondre

0

Essayez RepaintManager.currentManager (composant) .markCompletelyClean (composant). Cela empêchera le composant de repeindre. Vous devrez peut-être faire cela après chaque ajout de nouveaux composants.

http://docs.oracle.com/javase/6/docs/api/javax/swing/RepaintManager.html#markCompletelyClean%28javax.swing.JComponent%29

+0

Pourquoi est-ce que je voudrais empêcher le composant de repeindre? Comment cela résoudra-t-il le problème de l'arrière JPanel n'étant pas visible une fois dessiné, et est derrière le front JPanel, étant repeint en permanence – Colourfit

+0

Je l'ai réussi à arrêter de repeindre! Ce n'est pas mon problème! Mon problème est que cela montre si je le repeins une fois. – Colourfit

+0

Pouvez-vous s'il vous plaît expliquer votre réponse? – Colourfit

0

Je ne sais pas si ces deux lignes de code

super.paintComponent(g); 
drawOnce(g); 

sont la racine du problème, je ne me souviens pas sincerly comment fonctionne paintComponent (un test pourrait aider) mais essayer pour les échanger:

drawOnce(g); 
super.paintComponent(g); 

peut-être, sur votre version originale, vous indique JVM pour peindre la totalité du composant et, seulement après que le AWTEvent a été ajouté à la file d'attente, à DRA w ce dont vous avez besoin. Je suppose que la documentation de l'awt va l'expliquer.