我正在使用JFrame
设置纸牌游戏,使用扩展JLabel
的卡片,以便可以在屏幕上拖动它们。但是,我的一个要求是我可以双击一张卡片,它可以快速连接到4个A盘。这不是问题。造成问题的原因是我把它设置在一个数组中,这样aces会到达与ace的套装相对应的位置,然后如果卡被拖到那里,我会重新排列。如果双击,则A必须转到第一个点(从左侧)然后转到第二个点,依此类推。我本来打算用getComponentAt()
找出第一个位置的内容,如果我可以将ace放在那里,如果没有,那么我继续前进到第二个等等。但是出于某些原因,即使我将参数硬编码到getComponentAt()
到我知道有一个组件的点,它仍然返回null。
这是我的代码的相关部分:
Container contentPane = getContentPane();
contentPane.setLayout(null);
...
for(int i = 0; i < 4; i++)
{
aces[i] = new Card();
aces[i].setBounds((i * 75) + 475, 25, 75, 100);
contentPane.add(aces[i]);
aces[i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
aces[i].setSuit(i + 1);
}
System.out.println(contentPane.getComponentAt(475, 25));
每次都返回null
,无论我在组件的哪个位置放置坐标。
有什么解释吗?
*更新了SSCCE: 这是主要类,单人纸牌:
import java.util.*;
import javax.swing.*;
import java.awt.*;
public class Solitaire extends JFrame
{
private Container contentPane;
private Card aces[];
public static void main(String args[])
{
Solitaire frame = new Solitaire();
frame.setVisible(true);
}
public Solitaire()
{
super();
contentPane = getContentPane();
contentPane.setLayout(null);
contentPane.setBackground(Color.GREEN.darker().darker());
setTitle("Solitaire");
setSize(800,800);
setResizable(false);
setLocation(250, 50);
setDefaultCloseOperation(EXIT_ON_CLOSE);
play();
}
public void play()
{
contentPane.removeAll();
aces = new Card[4];
for(int i = 0; i < 4; i++)
{
aces[i] = new Card(0,i + 1);
aces[i].setBounds((i * 75) + 475, 25, 75, 100);
contentPane.add(aces[i]);
aces[i].setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
}
for(int i = 0; i < contentPane.getComponents().length; i++)
System.out.println(contentPane.getComponents()[i]);
System.out.println(contentPane.getComponentAt(475, 25));
repaint();
}
}
这是Class Card:
import javax.swing.*;
public class Card extends JLabel
{
private int numb;
private int value;
private int suit;
public Card(int n, int s)
{
super();
numb = n;
suit = s;
}
}
如果你需要更多来解决这个问题的话,这就适合我。
答案 0 :(得分:3)
使用getComponentAt
首先,必须实际实现父容器的大小。如果没有,它将返回null
。如果该位置不存在子项,则该方法能够返回容器本身。
然后我的孩子Component#contains
进行测试以查看给定点是否直接感受到子组件内部,但是这需要将该点转换为子的坐标空间......
相反,我只是直接进入getBounds
......
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Point;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestComponentLocation {
public static void main(String[] args) {
new TestComponentLocation();
}
public TestComponentLocation() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.pack();
frame.setLocationRelativeTo(null);
Container contentPane = frame.getContentPane();
contentPane.setLayout(null);
for (int i = 0; i < 4; i++) {
JPanel panel = new JPanel();
panel.setBounds((i * 75) + 475, 25, 75, 100);
System.out.println(panel.getBounds());
contentPane.add(panel);
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 3));
}
System.out.println(getComponentAt(contentPane, new Point(475, 25)));
System.out.println(getComponentAt(contentPane, new Point(100, 25)));
frame.setVisible(true);
}
});
}
public Component getComponentAt(Container parent, Point p) {
Component comp = null;
for (Component child : parent.getComponents()) {
if (child.getBounds().contains(p)) {
comp = child;
}
}
return comp;
}
}