带有LayoutManager的JLayeredPane [英] JLayeredPane with a LayoutManager
问题描述
情况:像在纸牌游戏中一样,画一堆纸牌.堆得很好.
The situation: drawing a stack of playing cards, like in the Solitaire game. Nicely stacked.
为实现这一点,我将JLayeredPane
与LayoutManager
接口的自定义实现结合使用.使用自定义LayoutManager的原因是堆栈方向各不相同,有时纸牌彼此完全覆盖,有时彼此覆盖,有时这种逻辑对于LayoutManager似乎是一件好事,因为这基本上可以归结为设置布局位置.卡.
To achieve this, I'm using a JLayeredPane
in combination with a custom implementation of the LayoutManager
interface. The reason for using a custom LayoutManager is that the stack orientation varies, sometimes the playing cards cover each other completely, sometimes partially, and this logic seems to be a good job for a LayoutManager, because this basically boils down to setting the location of the cards.
因此,LayoutManager
负责设置堆栈中所有组件的X坐标和Y坐标.另一方面,JLayeredPane
负责Z坐标(通过其层).
So, the LayoutManager
is responsible for setting the X- and Y-coordinates of all components in my stack. The JLayeredPane
on the other hand is responsible for their Z-coordinates (via its layers).
将组件添加到JLayeredPane
就像这样:
Adding a component to a JLayeredPane
goes like this:
JLayeredPane pane = new JLayeredPane();
pane.setLayout(new StackLayout(...));
pane.add(new CardView(...), new Integer(j));
其中,new Integer(j)
是卡的层.由于JLayeredPane
的约定,必须为Integer
.
where new Integer(j)
is the layer of the card. This must be an Integer
due to the contract of JLayeredPane
.
这里的问题是,由于上述原因,我的StackLayout
除Integer
外不能具有任何其他约束对象. LayoutManager
界面要求您实现以下方法:
The problem here is, that my StackLayout
cannot have any other constraint object than an Integer
, due to the reason stated above. The LayoutManager
interface requires you to implement the following method:
addLayoutComponent(Component comp, Object constraints);
和传递的Object
在这里始终是Integer
.
and the passed Object
will here always be an Integer
.
在我的特殊情况下,我很幸运,因为我的XY坐标可以基于Z坐标进行计算.例如,图层k
中的卡片必须位于Y坐标k * offset
处.因此,在我的情况下,约束对象为Integer
没问题.
In my particular situation, I am lucky, as my XY-coordinates can be calculated based on the Z-coordinates. For example, the card in layer k
has to be located at Y-coordinate k * offset
. So in my situation, the constraints object being an Integer
is not a problem.
我想知道Z坐标和XY坐标之间没有相关性时应该怎么做?那你怎么解决呢?例如,如何将GridBagLayout
与JLayeredPane
结合使用,其中第一个需要一个GridBagConstraints
对象,第二个需要一个Integer
对象?当然,GBL的布局方式不会使组件重叠,但这仅是想法.
I was wondering what you should be doing when there is no correlation between the Z-coordinates and the XY-coordinates? How can you solve this then? For example, how would I use a GridBagLayout
in combination with a JLayeredPane
, where the first requires a GridBagConstraints
object and the second an Integer
object? Of course, a GBL will layout in such a way that components do not overlap, but it's just the idea.
推荐答案
基于Hovercraft Full Of Eels的评论,我将回答我自己的问题.
Based on the comment of Hovercraft Full Of Eels, I'll answer my own question.
呼叫JLayeredPane.add(Component comp, Object constraints)
将呼叫addImpl(Component comp, Object constraints, int index)
. JLayeredPane本身会覆盖此方法,这是源代码:
Calling JLayeredPane.add(Component comp, Object constraints)
will call addImpl(Component comp, Object constraints, int index)
. This method is overridden by JLayeredPane itself, here's the source:
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
是:
As you can see, the Integer
object is intercepted, so that the JLayeredPane knows the layer in which comp
should be placed. Then, it passes on constraints
, the Integer, to the super implementation. The essential part in the super implementation, Container
, is:
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的约束对象.
The solution would therefore be to extend JLayeredPane
and override its addImpl(Component comp, Object constraints, int index)
method, which can accept any Object of your choice: this object should contain the Integer
needed for the JLayeredPane's layer decision, and it should also contain the constraints object for the chosen LayoutManager.
StackConstraints:
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扩展名:
JLayeredPane extension:
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();
}
这篇关于带有LayoutManager的JLayeredPane的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!