简体   繁体   English

当我修改JPanel使其可见后,paintComponent在componentResize之前被调用

[英]When I modify a JPanel after it becomes visible, paintComponent gets called before componentResized

I have a data plot with a color bar that's a JPanel with a layout that has two JPanel s inside of it. 我有一个带有颜色条的数据图,该颜色条是一个JPanel ,其布局中包含两个JPanel One JPanel is the data plot itself, and the other is the color bar. 一个JPanel是数据图本身,另一个是颜色栏。 I'd like to add functionality so the color bar can be toggled on and off, and I've gone about this by simply removing the JPanel containing the color bar. 我想添加功能,以便可以打开和关闭颜色栏,而我通过简单地删除包含颜色栏的JPanel来解决此问题。 Something like this: 像这样:

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;
}

The problem is that when the color bar is removed, the data plot has a component listener with the componentResized method overrided which correctly resizes the data (maintains fixed aspect ratio) to fit the size of the JPanel. 问题是,当删除颜色栏时,数据图具有一个组件侦听器,该组件侦听器已覆盖componentResized方法,该方法可以正确调整数据大小(保持固定的宽高比)以适合JPanel的大小。 Something like this: 像这样:

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);  
        ....
    }  

}

It turns out that as-is, the dataplot is not resizing properly. 事实证明,数据图未正确调整大小。 I did some debugging and I found out that componentResized gets called AFTER the paintComponent method when I toggle the color bar off and on. 我进行了一些调试,发现当我打开和关闭颜色条时, componentResizedpaintComponent方法之后被调用。 This means the image gets painted, and then the scaleFactor gets updated afterwards, which is incorrect. 这意味着先绘制图像,然后再scaleFactor ,这是不正确的。 The only way I've been able to fix it so far is to call repaint() at the very end of the componentResized method. 到目前为止,我能够解决的唯一方法是在componentResized方法的最后调用repaint() However, repaint() is already called when the component is resized, so I feel like this is the incorrect approach. 但是,调整组件大小时已经调用了repaint() ,所以我觉得这是不正确的方法。 Some googled led me to solutions involving the use of revalidate and repaint after modifying a JPanel on demand. 一些谷歌搜索使我找到了在按需修改JPanel之后涉及使用revalidaterepaint解决方案。 However, any combination of doing this still led to componentResized being called after repaint . 但是,这样做的任何组合仍然导致在repaint之后调用componentResized Is there a standard fix for this? 有标准的解决方案吗?

An answer proposed in this thread offers an easy solution; 此主题中提出的答案提供了一个简单的解决方案。 rather than overriding the componentResized method, do the setBounds(int,int,int,int) one. 而不是重写componentResized方法,而是执行setBounds(int,int,int,int)一个。

The call order of componentResized, setBounds, and repaint is strange; componentResized,setBounds和repaint的调用顺序很奇怪。 on program startup it is like this; 在程序启动时就是这样;

  • setBounds 的setBounds
  • componentResized 的componentResized
  • repaint 重绘

while if you manually resize it later (I did not test with in-code resizing order) it goes 而如果您稍后手动调整大小(我没有按代码中的调整大小顺序进行测试),

  • setBounds 的setBounds
  • repaint 重绘
  • componentResized 的componentResized

By setting your flags in setBounds rather than componentResized, you can know to recompute your repaint size-sensitive variables on panel resizing, effective immediately. 通过在setBounds中设置标志,而不是在componentResized中设置标志,您可以知道重新调整面板大小时重新绘制尺寸敏感的变量,立即生效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM