2014-09-23 16 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你的标志,你就可以知道重新计算上面板调整您的重绘大小敏感的变量,立即生效。

相关问题