Question

I am using a JFrame to set up a game of Solitaire, using Cards that extend JLabel so that they can be dragged around the screen. However, one of my requirements is that I be able to double click a card and it snaps up to the 4 stacks of aces. This is not a problem. what is causing problems is that I set this up in an array, so that the aces would go to the spot that corresponds with the suit of the ace, then I have the spots rearrange if a card is dragged up there. If it is double clicked, the aces must go to the first spot (from the left) then the second, and so on. I had planned to use getComponentAt() to find out what was at the first spot and if I could place the ace there, if not then i move on to the second and so on. For some reason though, even if I hard code in the parameters into getComponentAt() to spots I know have a component, it is still returning null.

this is the relevant portion of my code:

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));

This is returning null every time, no matter where in the component i put the coordinates. Any explanations?

*Updated SSCCE: This is the main class, solitaire:

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();
    }
}

and this is 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;
    }
}

This ran for me, comment if you need more to solve the problem.

Was it helpful?

Solution

There are lots of problems with using getComponentAt

The first is, the parent container must actually be realized and sized. If not, it will return null. The method is capable of returning the container itself if no children exist at the location.

I then child Component#contains to test to see if the given point feel within the child components directly, but this wants the point to be translated into the child's coordinate space...

So instead, I simply went straight to 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;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top