当我将JPanel变为可见后修改它时,paintComponent会在componentResized之前被调用

时间:2014-09-23 02:15:26

标签: java swing jpanel

我有一个数据图,其颜色条为JPanel,其布局内部有两个JPanel。一个JPanel是数据图本身,另一个是颜色条。我想添加功能,以便可以打开和关闭颜色条,我只需删除包含颜色条的JPanel即可。像这样:

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方法,可以正确调整数据大小(保持固定的宽高比)以适合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随后更新,这是不正确的。到目前为止,我能够解决它的唯一方法是在repaint()方法的最后调用componentResized。但是,在调整组件大小时已调用repaint(),因此我觉得这是不正确的方法。一些谷歌搜索引导我到解决方案涉及使用revalidaterepaint后修改JPanel按需。但是,执行此操作的任何组合仍会导致在componentResized之后调用repaint。这是否有标准的解决方案?

1 个答案:

答案 0 :(得分:0)

this thread中提出的答案提供了一个简单的解决方案;而不是覆盖componentResized方法,而不是setBounds(int,int,int,int)。

componentResized,setBounds和repaint的调用顺序很奇怪;程序启动就像这样;

  • 的setBounds
  • 的componentResized
  • 重绘

如果您稍后手动调整大小(我没有使用代码内调整大小顺序进行测试),那么

  • 的setBounds
  • 重绘
  • 的componentResized

通过在setBounds而不是componentResized中设置标志,您可以知道在面板大小调整时重新计算重绘大小敏感变量,立即生效。