带有LayoutManager的JLayeredPane

时间:2013-08-20 12:19:28

标签: java swing constraints layout-manager jlayeredpane

情况:画出一堆扑克牌,就像在纸牌游戏中一样。很好地堆积。

为实现这一目标,我将JLayeredPaneLayoutManager接口的自定义实现结合使用。使用自定义LayoutManager的原因是堆栈方向不同,有时候扑克牌完全相互覆盖,有时是部分覆盖,这个逻辑对于LayoutManager来说似乎是一个很好的工作,因为这基本上归结为设置的位置。卡。

因此,LayoutManager负责设置堆栈中所有组件的X坐标和Y坐标。另一方面,JLayeredPane负责其Z坐标(通过其图层)。

将组件添加到JLayeredPane是这样的:

JLayeredPane pane = new JLayeredPane();
pane.setLayout(new StackLayout(...));
pane.add(new CardView(...), new Integer(j));

其中new Integer(j)是卡片的图层。由于Integer的合同,这必须是JLayeredPane

这里的问题是,由于上述原因,我的StackLayout不能拥有任何其他约束对象而不是IntegerLayoutManager接口要求您实现以下方法:

addLayoutComponent(Component comp, Object constraints);

,传递的Object将始终为Integer

在我的特殊情况下,我很幸运,因为我的XY坐标可以根据Z坐标计算。例如,图层k中的卡片必须位于Y坐标k * offset。所以在我的情况下,约束对象是Integer不是问题。

我想知道当Z坐标和XY坐标之间没有相关性时你应该做什么?你怎么解决这个问题呢?例如,如何将GridBagLayoutJLayeredPane结合使用,其中第一个需要GridBagConstraints个对象,第二个需要Integer个对象?当然,GBL将以这样的方式布局,即组件不会重叠,但这只是想法。

2 个答案:

答案 0 :(得分:3)

根据Hovercraft Full Of Eels的评论,我会回答我自己的问题。

致电JLayeredPane.add(Component comp, Object constraints)将致电addImpl(Component comp, Object constraints, int index)。 JLayeredPane本身重写了这个方法,这里是源代码:

protected void addImpl(Component comp, Object constraints, int index) {
    int layer;
    int pos;

    if(constraints instanceof Integer) {
        layer = ((Integer)constraints).intValue();
        setLayer(comp, layer);
    } else
        layer = getLayer(comp);

    pos = insertIndexForLayer(layer, index);
    super.addImpl(comp, constraints, pos);
    comp.validate();
    comp.repaint();
    validateOptimizedDrawing();
}

如您所见,Integer对象被拦截,因此JLayeredPane知道应放置comp的图层。然后,它将constraints(整数)传递给超级实现。超级实现的基本部分Container是:

protected void addImpl(Component comp, Object constraints, int index) {
    ...
    if (layoutMgr != null) {
        if (layoutMgr instanceof LayoutManager2) {
           ((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
        } else if (constraints instanceof String) {
           layoutMgr.addLayoutComponent((String)constraints, comp);
        }
    }
    ...
}

因此,解决方案是扩展JLayeredPane并覆盖其addImpl(Component comp, Object constraints, int index)方法,该方法可以接受您选择的任何对象:此对象应包含JLayeredPane层决策所需的Integer ,它还应该包含所选LayoutManager的约束对象。

StackConstraints:

public final class StackConstraints {
    public final int layer;
    public final Object layoutConstraints;
    public StackConstraints (int layer, Object layoutConstraints){
        this.layer = layer;
        this.layoutConstraints = layoutConstraints;
    }
}

JLayeredPane扩展名:

protected void addImpl(Component comp, Object constraints, int index) {
    int layer;
    int pos;
    Object constr;
     if(constraints instanceof StackConstraints) {
        layer = constraints.layer.intValue();
        constr = ((StackConstraints) constraints).layoutConstraints;
        setLayer(comp, layer);
    } else {
        layer = getLayer(comp);
        constr = constraints;
    }

    pos = insertIndexForLayer(layer, index);
    super.addImpl(comp, constraints, pos);
    comp.validate();
    comp.repaint();
    validateOptimizedDrawing();

}

答案 1 :(得分:2)

  

因此,LayoutManager负责设置堆栈中所有组件的X坐标和Y坐标。另一方面,JLayeredPane负责其Z坐标(通过其层)。

您无需为此使用分层窗格。面板还支持Z-Order。查看Overlap Layout,它可以解释更多相关信息,并可以满足您的需求。