2016-07-26 61 views
0

我有一個自定義JPanel,落後於另一個自定義JPanel,在一個JLayeredPane。我只想畫背景JPanel一次。因爲它不會改變。這將節省系統資源。我如何成功地做到這一點?爲什麼這個JPanel不可見?

我知道如果我允許背景JPanel像前景JPanel一樣被重複繪製,它會被看到。但是那不顧我的目標。哪一個只繪製一次。

重新迭代。我如何繪製背景JPanel一次,然後遞歸地繪製前景JPanel,同時兩個JPanel都在JLayeredPane中看到,其中背景JPanel位於前景之後JPanel

這是我目前的嘗試。這不起作用。這個代碼的問題是,背景JPanel是根本不可見的「

這個問題不是重複的,因爲人們都在尋找不相關的問題。我現在已經提出了這個問題來解決我想解決的問題。如果它可以幫助你解決我的問題。那麼這個問題的鏈接就在這裏。 question。 這個問題也有一個不好的,毫無意義的答案。我甚至還嘗試過並且無法工作。

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(); 

     RepaintManager.currentManager(backPanel).markCompletelyClean(backPanel); 

    } 

    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){ 
      if (!drawn){ 
       super.paintComponent(g); 
       g.setColor(Color.red); 
       g.fillRect(0, 0, screenSize.width, 200); 
       System.out.println("Reccursion"); 
       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

你怎麼知道背景JPanel必須再次繪製?另外,你爲什麼需要它只繪製一次? –

+1

[如何成功繪製背景JPanel一次並不斷更新前景JPanel?](http://stackoverflow.com/questions/38572290/how-to-successfully-draw-background-jpanel-once-and-update-前景-jpanel-con) – resueman

+0

@LakshyaGoyal「你怎麼知道JPanel的背景需要再次繪製?不要在這裏得到你想說的話。 「另外,你爲什麼需要它只能繪製一次?」我不需要。我要。改進我的程序如何執行。這只是一個mvce。不是我的整個計劃 – Colourfit

回答

2

首先是一些一般的評論。您不應該:

  1. 延長JLayeredPane。
  2. 使用靜態變量
  3. 使用,而真正的循環

如果這是一個MCVE沒關係。一個MCVE應該使用適當的結構,否則我們可能會認爲你在真實代碼中犯了上述錯誤。

在while循環使用:

repaint(); 

好了,你的代碼延伸的JLayeredPane所以分層窗格中的所有層都畫。

如果您只想重新繪製一個面板,則僅在該面板上調用repaint()。然而,這可能會導致問題,因爲您需要確保背景已清除,然後再進行任何繪畫,這就是爲什麼背景也需要繪製的原因。

如果您不想重新繪製整個背景,那麼您需要明確哪些區域需要重新繪製。查看Custom Painting上的Swing教程中的部分,其中顯示瞭如何優化繪製的內容。請注意0​​方法如何在兩個不同的區域上調用repaint()兩次。這將導致較小的背景區域被重新粉刷。

+1

你能解釋爲什麼擴展JLayeredPane不好嗎?什麼是錯誤的靜態變量?使用while循環只是一種輕鬆展示我的問題的方法。在我的真實項目中,我使用了更好的遊戲循環。 – Colourfit