我有一个带有颜色栏的数据图,该颜色栏是一个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()
,所以我觉得这是不正确的方法。一些谷歌搜索使我找到了按需修改revalidate
后使用repaint
和JPanel
的解决方案。但是,执行此操作的任何组合仍导致在componentResized
之后调用repaint
。有标准的解决方案吗? 最佳答案
this thread中提出的答案提供了一个简单的解决方案。而不是重写componentResized方法,而是执行setBounds(int,int,int,int)一个。
componentResized,setBounds和repaint的调用顺序很奇怪。在程序启动时就是这样;
setBounds
componentResized
重涂
而如果您稍后手动调整大小(我未按代码中的调整大小顺序进行测试)
setBounds
重涂
componentResized
通过在setBounds中设置标志,而不是在componentResized中设置标志,您可以知道重新调整面板大小时重新绘制尺寸敏感的变量,立即生效。