Harsha
Harsha

Reputation: 3578

Get location of a swing component

I have put some JPanels into another JPanel which its' layout is Box Layout and Y-Axis. After I have put all the panels I need to get the Y position of each added JPanel in from the JPanel container panel. But, when I try to get that I always get zero for Y position of each JPanel. Please tell me how to get the Y position of each Jpanel from the JPanel container JPanel.

This is what I have done,

JPanel panelHolder = new JPanel(new BoxLayout(this, BoxLayout.Y_AXIS));
for(int i = 0; i< 10; i++){
   JPanel p = new JPanel(); 
   panelHolder.add(p);
}

int componentCount = panelHolder.getComponentCount();

for (int j = 0; i < componentCount ; j++) {

  Component c = pnlRowHolder.getComponent(i);
  JPanel p = (JPanel)c;
  System.out.println(p.getY());//I get zero for all
}

Upvotes: 9

Views: 32442

Answers (6)

Andrea Annibali
Andrea Annibali

Reputation: 389

Suppose you have Jpanel father that contains a JPanel son. If cx is the coordinate x of the son with respect to the father and cy is the coordinate y of the son with respect to the father, then:

cx = son.getLocationOnScreen().getX()-father.getLocationOnScreen().getX()

cy = son.getLocationOnScreen().getY()-father.getLocationOnScreen().getY()

I think is the easiest way...

Upvotes: 2

Terry
Terry

Reputation: 14877

The problem is often that the layout or the drawing is done only after the whole method returned. In that case, getX and getY return 0.

It may help to call pack() on the frame window, or doLayout() or validate() on the JPanel you are working on. But often it doesn't help, because you have little influence on the internal scheduling: http://www.oracle.com/technetwork/java/painting-140037.html

What does help me in this case is to put the part where I need the X and Y location into a worker thread:

JPanel panelHolder = new JPanel(new BoxLayout(this, BoxLayout.Y_AXIS));
for(int i = 0; i< 10; i++){
    JPanel p = new JPanel(); 
    panelHolder.add(p);
}

int componentCount = panelHolder.getComponentCount();

SwingUtilities.invokeLater(new Runnable() {         
    @Override
    public void run() {
        for (int j = 0; i < componentCount; j++) {    
            Component c = pnlRowHolder.getComponent(i);
            JPanel p = (JPanel) c;
            System.out.println(p.getY());
        }
    }
});

This way getting the X and Y will be postponed until the layout is done.

Upvotes: 1

davidXYZ
davidXYZ

Reputation: 729

Pack the frame before getting position. It seems everything overlaps each other starting at origin (0,0) until you pack.

Here's a working code:

import java.awt.Component;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestBoxLayout {

    public static void main(String[] args) {
        JFrame frame = new JFrame();

        JPanel panelHolder = new JPanel();
        panelHolder.setLayout(new BoxLayout(panelHolder, BoxLayout.Y_AXIS));

        for (int i = 0; i < 10; i++) {
            JPanel p = new JPanel();
            p.setPreferredSize(new Dimension(100, 13)); //I set the height just to make sure.
            panelHolder.add(p);
        }
        frame.add(panelHolder);

        /**
         * Pack before you get the position.
         */
        frame.pack();

        int componentCount = panelHolder.getComponentCount();
        for (int j = 0; j < componentCount; j++) {
            Component c = panelHolder.getComponent(j);
            JPanel p = (JPanel) c;
            System.out.println(p.getY());//I get 0, 13, 26, 39, .....
        }

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

Result:

0
13
26
39
52
65
78
91
104
117

Note: The signature for BoxLayout is BoxLayout(Container target, int axis). The target is the stuff you are setting your layout to. For this reason, if you want use a BoxLayout, you should always create the panel first. Then use component.setLayout() so that the target already exists. The this in your JPanel constructor was referring to something else, not panelHolder. I guess the class you created this function in is also a subclass of Container and that is why you didn't get an error.

Upvotes: 4

mKorbel
mKorbel

Reputation: 109813

Please tell me how to get the Y position of each Jpanel from the JPanel container JPanel.

  • BoxLayout accepting XxxSize (Preferred in this case) that returns its child,

  • JPanel returns (0, 0) this is correct value

  • this or simlair result you can get from all LayoutManager, for example built_in FlowLayout for JPanel (accepting only the PreferredSize), returns the same coordinates (0, 0)

  • excepting BorderLayout then is there generated 10pixels(for W, E, N, S areas), and valid only in the case that CENTER area is used for some JComponent

  • JPanel is Container and by empty JPanel by defualt returns zero size on the screen,

  • JPanel can to returns proper coordinates if is there any JComponent or you override XxxSize in the JPanel constructor

Upvotes: 1

David Kroukamp
David Kroukamp

Reputation: 36423

Add your JPanel to the JFrames contentPane thus allowing you to get the X and Y co ordinates using getX() and get() though I'd suggest adding all components first, as the points may change as more components are added and then as trashgod said simply call pack() on the frame instance.

I did a short sample to demonstrate:

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Test().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        initComponents(frame);
        
        frame.pack();//call pack 
        
        printPanelCompPoints(mainPanel);//produces correct coords
        
        frame.setVisible(true);
    }
    
    private JPanel mainPanel;

    private void initComponents(JFrame frame) {
        mainPanel = new JPanel(new BorderLayout());
        JPanel centerPanel = new JPanel();
        JPanel northPanel = new JPanel();
        JPanel southPanel = new JPanel();
        JPanel westPanel = new JPanel();
        JPanel eastPanel = new JPanel();

        centerPanel.add(new JLabel("CENTER"));
        northPanel.add(new JLabel("NORTH"));
        eastPanel.add(new JLabel("EAST"));
        southPanel.add(new JLabel("SOUTH"));
        westPanel.add(new JLabel("WEST"));

        mainPanel.add(centerPanel, BorderLayout.CENTER);
        mainPanel.add(northPanel, BorderLayout.NORTH);
        mainPanel.add(southPanel, BorderLayout.SOUTH);
        mainPanel.add(eastPanel, BorderLayout.EAST);
        mainPanel.add(westPanel, BorderLayout.WEST);

       frame.getContentPane().add(mainPanel);
    
       printPanelCompPoints(mainPanel);//produces all 0's
    }

    private void printPanelCompPoints(JPanel mainPanel) {
        for (int i = 0; i < mainPanel.getComponentCount(); i++) {
            System.out.println(mainPanel.getComponent(i).getX() + ", " + mainPanel.getComponent(i).getY());
        }
    }
}

As you can see calling printPanelCompPoints(mainPanel); in initComponents(JFrame frame) produces all 0's, (as they have been added to the frame but `pack() has not been called).

0, 0

0, 0

0, 0

0, 0

0, 0

however in the createAndShowUI() after calling pack() on the JFrames instance calling printPanelCompPoints(mainPanel); produces the correct co-odrinates:

44, 26

0, 0

0, 52

99, 26

0, 26

Upvotes: 3

MadProgrammer
MadProgrammer

Reputation: 347234

Coordinates are relative to their parent. In your exemple, all the child components are being added along the top of the parent container, making there y position 0 (relative to their parent).

Try adding an empty border to the parent container, you should see the y position change.

You can use the SwingUtilities.convertPoint to convert between coordinate systems

Upvotes: 4

Related Questions