2016-07-25 63 views
0

我有一個自定義的JLayeredPane,我正在重繪它在我的遊戲循環中。 JLayeredPane中添加了兩個自定義JPanel。這些是前景和背景JPanels。我怎樣才能成功地只繪製一次背景JPanel(當重新調整窗口大小或任何其他原因時重繪)以減少對系統資源的影響,同時不斷更新我的前景JPanel。如何成功繪製背景JPanel一次並不斷更新前景JPanel?

要重新迭代,我不想在一個循環中不斷重繪背景JPanel。因爲背景沒有改變,所以我只想重新繪製它。並且很大。

在我嘗試做到這一點時,我只畫了一次背景。然而。後臺JPanel根本不可見。而前臺JPanel更新正常。它幾乎就像前景JPanel在背景JPanel上繪製,即使我將兩個JPanel設置爲setOpaque(false)

我已經制作了一個mvce,它顯示了我的嘗試只繪製一次背景JPanel,同時更新前景JPanel不斷。

我的代碼的問題是背景JPanel不顯示。

現在。我知道,如果我不斷繪製它會顯示。但是這打破了我想要做的事情的目的。我試圖只繪製一次,並同時被看到

我的代碼成功只繪製了背景JPanel一次。問題是後臺JPanel不顯示。如何解決這個問題

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

'增加FPS'爲什麼你需要增加幀率?考慮使用javax.swing.Timer來更好地控制fps並以特定幀速率刷新(比如60fps - 換句話說增加fps不一定有利) – copeg

+0

@copeg在我的實際項目中,我嘗試訪問儘可能最高的FPS,並不斷更新我的遊戲,每秒鐘60次。我已經重申了我的答案,即表示使用更少的系統資源,而不是增加FPS。 – Colourfit

+1

Swing繪畫系統設計爲在必要時重新繪製 - 如果您的繪畫例程比較複雜並且您希望僅執行一次,請考慮第一次繪製到BufferedImage,然後將圖像繪製到JPanel – copeg

回答

0

嘗試RepaintManager.currentManager(組件).markCompletelyClean(組件)。它會阻止組件重新粉刷。您可能需要在每次添加新組件後執行此操作。

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

+0

我爲什麼要防止組件重新粉刷?這將如何解決後面的JPanel只在繪製一次時不可見的問題,並且在正面JPanel後面,正在不斷重新繪製 – Colourfit

+0

我已成功地將其停止重新繪製!那不是我的問題!我的問題是,如果我重新繪製一次,它就會顯示出來。 – Colourfit

+0

你能解釋你的答案嗎? – Colourfit

0

我不知道的代碼

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

這兩條線是問題的根源,我誠懇不記得的paintComponent是如何工作的(測試可能有所幫助),但嘗試交換它們:

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

也許,您的原始版本,你告訴JVM繪製整個組件,並只有在AWTEvent中已經添加到隊列中,以DRA你需要什麼。 我想awt的文檔會解釋它。