问题
Can anybody explain why circular reference is being set twice in the followig code?
//declare panel
this.cntnrPnl = new JPanel();
//define layout manager for the panel - but why circ ref?
this.cntnrPnl.setLayout(new BoxLayout(this.cntnrPnl, BoxLayout.Y_AXIS));
Why is it necessary to link the BoxLayout
back to the JPanel
container explicitly instead of JPanel.setLayout
doing the setting itself behind the scene and using a setter from BoxLayout
for code compactness?
E.g.:
this.cntnrPnl.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
//and then in JPanel.setLayout have something line
_layout.setContainer(this);
回答1:
Because BoxLayout is a special layout that needs a reference to the target container it lays out. That's not the case of all the layout managers. It would be ugly to add a specific case for BoxLayout in the setLayout()
method. And it would also mean that the BoxLayout would be in an unstable state after its construction, since it wouldn't have the mandatory target container yet.
The reverse could have been done though: having the BoxLayout constructor call setLayout(this)
on the target container. But I don't know why it hasn't been done.
回答2:
Why is it necessary to link the
BoxLayout
back to theJPanel
container explicitly instead ofJPanel.setLayout
doing the setting itself behind the scene and using a setter fromBoxLayout
for code compactness?
What you call JPanel.setLayout
is actually Container.setLayout:
public void setLayout(LayoutManager mgr)
You call call the method with a BoxLayout
because it implements LayoutManager
. But LayoutManager
does not have a setContainer
method, so it would not have worked without adding that method. But it seems that most layout managers don't care about a container so the method would not belong there.
Would it be possible for BoxLayout
constructor to do the magic? Maybe not, though a BoxLayout
is tied to a Container
, the reverse is not necessarily true. Consider:
this.cntnrPnl = new JPanel();
BoxLayout bY = new BoxLayout(this.cntnrPnl, BoxLayout.Y_AXIS);
BoxLayout bX = new BoxLayout(this.cntnrPnl, BoxLayout.X_AXIS);
Now at different times you can call this.cntnrPnl.setLayout(bX)
and this.cntnrPnl.setLayout(bY)
.
So looking at all options, it seems the current API is best, though of course all this is somewhat subjective.
By the way, please consider renaming cntnrPnl
to containerPanel
. You are not really saving much by stripping the vowels.
回答3:
Because a JPanel is not the only available container in Swing. In particular, you might create your own container class and not know about those special requirements for BoxLayout. As a result, the layout manater would not work for your implementation.
Now one could ask why the BoxLayout needs a reference to the JPanel to begin with, but this is a different matter.
来源:https://stackoverflow.com/questions/13810075/java-swing-layout-manager-circular-reference-being-set-twice