简体   繁体   中英

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. One JPanel is the data plot itself, and the other is the color bar. 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. 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. 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. This means the image gets painted, and then the scaleFactor gets updated afterwards, which is incorrect. The only way I've been able to fix it so far is to call repaint() at the very end of the componentResized method. However, repaint() is already called when the component is resized, so I feel like this is the incorrect approach. Some googled led me to solutions involving the use of revalidate and repaint after modifying a JPanel on demand. However, any combination of doing this still led to componentResized being called after repaint . 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.

The call order of componentResized, setBounds, and repaint is strange; on program startup it is like this;

  • setBounds
  • componentResized
  • repaint

while if you manually resize it later (I did not test with in-code resizing order) it goes

  • setBounds
  • repaint
  • 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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