2014-09-23 76 views
0

我有一個顏色欄的JPanel數據情節與其中有兩個JPanel s的佈局。其中一個JPanel是數據圖本身,另一個是彩條。我想添加功能,以便可以打開和關閉顏色條,並且通過簡單地刪除包含顏色條的JPanel來解決這個問題。是這樣的:當我修改一個JPanel後,它變得可見,paintComponent被調用之前componentResized

public class Data2DPlotWithColorBar extends JPanel { 
    public Data2DPlotWithColorBar() { 
     this.data2DPlot = new Data2DPlot(); 
     this.colorBar = new VerticalColorBar(); 
     this.setPlot(); 
    } 

    public final void toggleColorBar() { 
     enableColorBar = !enableColorBar; 
     setPlot(); 
    } 

    private void setPlot() {     
     this.removeAll(); 
     this.setLayout(new BorderLayout()); 
     if (enableColorBar) { 
      this.add(colorBar, BorderLayout.EAST); 
     } 
     this.add(this.data2DPlot, BorderLayout.CENTER); 
     this.revalidate(); 
     this.repaint(); 
    } 

    private final Data2DPlot data2DPlot;  
    private final VerticalColorBar colorBar; 
    private boolean enableColorBar; 
} 

的問題是,當被除去的色條,數據圖具有與componentResized方法overrided其正確地調整大小的數據的組件監聽器(保持固定縱橫比)以適合的大小JPanel。類似這樣的:

public class Data2DPlot extends JPanel { 

    ... 

    @Override 
    public final void componentResized(ComponentEvent e) { 
     double scaleFactorBuf = Math.min((double)getPixelMaxViewWidth()/getNativeWidth(), 
             (double)getPixelMaxViewHeight()/getNativeHeight());  
     // Make sure scaleFactorBuf isn't close to zero 
     if (Math.abs(scaleFactorBuf) > MathUtilities.LAMBDA) { 
      scaleFactor = scaleFactorBuf; 
     } 
    } 


    ... 


    @Override 
    protected final void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     .... 
    } 

} 

事實證明,原樣,數據沒有正確調整大小。我做了一些調試,發現componentResized在我關閉和打開顏色條後調用paintComponent方法後。這意味着圖像被繪製,然後scaleFactor後來得到更新,這是不正確的。到目前爲止,我已經能夠修復它的唯一方法是在componentResized方法的末尾呼叫repaint()。但是,在調整組件大小時已調用repaint(),所以我覺得這是不正確的方法。一些Google搜索引導我轉向涉及使用revalidaterepaint的解決方案,然後根據需要修改JPanel。但是,這樣做的任何組合仍然導致在repaint之後調用componentResized。有沒有這個標準的修復?

+2

這似乎是一個複雜的設置,使得使用代碼片段和簡短的解釋很難完全理解。我們不希望看到整個程序,但如果您很快就沒有獲得幫助,請考慮創建併發布[最小,完整和可驗證示例程序](http://stackoverflow.com/help/mcve),其中您可以將代碼壓縮到仍然編譯和運行的最小位,沒有外部依賴性(例如需要鏈接到數據庫或映像),沒有額外的代碼與您的問題無關,但仍然表明您的問題。 – 2014-09-23 02:18:10

+2

請注意,'componentResized'可以快速連續多次調用,例如窗口大小調整時。我過去所做的是使用'javax.swing.Timer',設置爲不重複,並使用一個小延遲(〜100ms),每次調用componentResized時重新啓動它。這會阻止計時器觸發更新,直到100ms過去。一旦觸發,我執行我需要的更新並調用'repaint' ...另一種解決方案是重寫'invalidate'並重置緩衝區(爲'null'),並在調用緩衝區時使用'paintComponent'重建緩衝區緩衝區是'null') – MadProgrammer 2014-09-23 02:19:31

+0

@MadProgrammer現在主要的問題是它被調用的順序。我需要在'paintComponent'之前調用'componentResized'。出於某種原因,通過我上面的設置,'componentResized'在'paintComponent'之後的最後被調用。我會盡力得到一個完整的例子。 – Justin 2014-09-23 02:30:30

回答

0

this thread中提出的答案提供了一個簡單的解決方案;而不是重寫componentResized方法,請執行setBounds(int,int,int,int)。

componentResized,setBounds和repaint的調用順序很奇怪;在程序啓動時就是這樣;

  • 的setBounds
  • 的componentResized
  • 重繪

而如果您手動調整它後,它進入

  • 的setBounds
  • (我沒有與代碼調整爲了測試)
  • 重漆
  • 的componentResized

通過的setBounds而不是設置的componentResized你的標誌,你就可以知道重新計算上面板調整您的重繪大小敏感的變量,立即生效。

相關問題