> Use of overriding getPreferredSize() instead of using setPreferredSize() for fixed size Components
> Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
> Overriding setPreferredSize() and getPreferredSize()
看这个例子:
public class MyPanel extends JPanel{ private final Dimension dim = new Dimension(500,500); @Override public Dimension getPreferredSize(){ return new Dimension(dim); } public static void main(String args[]){ JComponent component = new MyPanel(); component.setPreferredSize(new Dimension(400,400)); System.out.println(component.getPreferredSize()); } }
有必要对setPreferredSize()
- Sets the preferred size of this component.
的getPreferredSize()
- If the preferredSize has been set to a non-null value just returns it. If the UI delegate’s getPreferredSize method returns a non null
value then return that; otherwise defer to the component’s layout
manager.
所以这样做清楚地打破了Liskov Substitution Principle.
prefferedSize是一个绑定属性,所以当你设置一个firePropertyChange被执行.所以我的问题是当你重写getPrefferedSize()不需要重写setPreferredSize(..)吗?
例:
public class MyPanel extends JPanel{ private Dimension dim = null; @Override public Dimension getPreferredSize(){ if(dim == null) return super.getPreferredSize(); return new Dimension(dim); } @Override public void setPrefferedSize(Dimension dimension){ if(dim == null) dim = new Dimension(500,500); super.setPreferredSize(this.dim); // } public static void main(String args[]){ JComponent component = new MyPanel(); component.setPreferredSize(new Dimension(400,400)); System.out.println(component.getPreferredSize()); } }
现在我们看到我们得到相同的结果,但是听众将会收到真正的值的通知,而且我们不会破坏LSP的原因setPreferredSize states设置这个组件的首选大小.但不是如何.
解决方法
我们是否违反了只覆盖getXXSize()(和setXXSize())的LSP?
不,如果我们正确地执行:-)第一个权限是属性的API文档,最好从它的起源,即组件:
Sets the preferred size of this component to a constant value. Subsequent calls to getPreferredSize will always return this value.
这是一个有约束力的合同,但是我们实现了getter,它必须遵守恒定值,如果设置:
@Override public Dimension getPreferredSize() { // comply to contract if set if(isPreferredSizeSet()) return super.getPreferredSize(); // do whatever we want return new Dimension(dim); }
XXSize是一个绑定的属性 – 是吗?
在JComponent的祖先中,仅有间接证据:实际上,组件在setter中触发PropertyChangeEvent. JComponent本身似乎记录了事实(粗体我):
@beaninfo
preferred: true
bound: true
description: The preferred size of the component.
哪个是…错误的:被绑定的属性意味着每当值改变时,需要通知监听器,这就是以下(伪测试)必须通过的:
JLabel label = new JLabel("small"); Dimension d = label.getPreferredSize(); PropertyChangeListener l = new PropertyChangeListener() ... boolean called; propertyChanged(...) called = true; label.addPropertyChangeListener("preferredSize",l); label.setText("just some longer text"); if (!d.equals(label.getPreferredSize()) assertTrue("listener must have been notified",l.called);
…但失败.由于某些原因(不知道为什么这可能被认为是适当的),他们希望xxSize的常数部分是一个绑定的属性 – 这样的覆盖是根本不可能的.当然可以(疯狂地猜测)一个历史性的问题:起初,只有摆放者才能获得(因为很好的理由).在它的backport到awt它突变成一个bean属性,它从来没有.