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
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.
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 PreferredSiz
e), 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
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
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.
Add your JPanel
to the JFrame
s 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 JFrame
s instance calling printPanelCompPoints(mainPanel);
produces the correct co-odrinates:
44, 26
0, 0
0, 52
99, 26
0, 26
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...