Reputation: 926
I'm creating background images with a java program which I upload to a site to use to display data. The images are based on parameters which create unique views and datapoints which i can upload to the server.
On the site, I add items to display data at specific locations on the screen. I've made it so my java program can create the backgrounds and the data points, but i have to manually configure the location of the data points by finding the right positions and configuring them as I go.
I would like to figure out the same positions of specific labels and panels inside my parent panel of my java program so i can store the points and use them later to generate positions for my data points so it can be automatized in the future.
My background structure is like so
Frame - Holds a JTabbedPane which switches between 4-10 different panels.
Each one of the tabbedpane panels is the main panel which becomes a background.
Inside each panel there are multiple subpanels which are organized using a GridbagLayout.
Each subpanel can have its own panels or labels which are positions im looking to record.
Here is a picture showing an example of one of the panels. The red boxes are the locations of the labels im looking to get a position of.
I tried using this code to find the positions and put them on the label but the positions are always at 0,0
public void positions(Container p1) {
for (Component p : p1.getComponents()) {
if (p instanceof JLabel) {
try {
if (((JLabel) p).getText().isEmpty()) {
Point spot = ((JLabel) p).getLocation();
((JLabel) p).setText(spot.toString());
}
} catch (NullPointerException e) {
}
//System.out.println(e.getMessage());
} else {
if (p instanceof JPanel) {
positions((Container) p);
}
}
}
}
This calls the function at the end of my update
mainPanel.revalidate();
mainPanel.repaint();
positions(mainPanel);
Update. I made a call to the above function from my frame class which updates each panel on the tabbed pane, then packs it, and then calls the function.
As you can see the positions are relative it its panel containing the label, rather than the panel which contains all the subpanels.
Upvotes: 2
Views: 2138
Reputation: 167
I had to position things manually with null layout. Then Robot needs correction in my context. X and Y location of all components was needed. I came up with next solution. When starting from constructor the "start" cannot be component itself but the parent at that moment.
public static int get_y_relation_to_app_frame(Container start) {
int y_accu = 0;
System.out.println(start.getClass().getSimpleName() + ":" + start.getY());
y_accu += start.getY();
Container parr = start;
try {
while ((parr = parr.getParent()) != null) {
if (!parr.getClass().getSimpleName().equals("JFrame")) {
y_accu += parr.getY();
System.out.println(parr.getClass().getSimpleName() + ":" + parr.getY());
System.out.println(" total=" + y_accu);
} else {
System.out.println("Main App found:" + parr.getClass().getSimpleName() + ":" + parr.getY());
y_accu += parr.getY();
System.out.println("Y total=" + y_accu);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return y_accu;
}
Upvotes: 0
Reputation: 926
Using Oliver Watkins advice on calling my method after pack i was able to use this to help get my final solution. Since the jlabels were inside panels which was inside a panel, i had to get the location of the panel relative to its parent panel. This was the code i used.
public void positions(Container p1) {
for (Component p : p1.getComponents()) {
if (p instanceof JLabel) {
try {
if (((JLabel) p).getText().isEmpty()) {
Rectangle r = p.getBounds();
// Panel of jlabel bounds compared to the main panels bounds
r = SwingUtilities.convertRectangle(p.getParent(), r, mainPanel);
// Wrong spot this is relative to the first panel
Point spot = ((JLabel) p).getLocation();
((JLabel) p).setText("x=" + spot.getX() + ", y=" + spot.getY());
// the r.toString() is the correct position as it is relative to the parent component
System.out.println("Position: " + spot.toString() + "\tr: " + r.toString());
}
} catch (NullPointerException | IllegalComponentStateException e) {
}
//System.out.println(e.getMessage());
} else {
if (p instanceof JPanel) {
positions((Container) p);
}
}
}
}
Upvotes: 1
Reputation: 34628
Instead of
if (((JLabel) p).getText().isEmpty()) {
Point spot = ((JLabel) p).getLocation();
((JLabel) p).setText(spot.toString());
}
If you want the position relative to the main panel, you should probably do:
Point spot = new Point();
Component currComponent = p;
while ( currComponent != null && currComponent != mainPanel ) {
Point relativeLocation = currComponent.getLocation();
spot.translate( relativeLocation.x, relativeLocation.y );
currComponent = currComponent.getParent();
}
((JLabel) p).setText(spot.toString());
This basically adds the coordinates of each JLabel
(this is inside the if
) to the coordinates of all its parents all the way up to mainPanel
.
Upvotes: 3
Reputation: 13509
Call your positions method after you call your pack() method on your Frame.
Upvotes: 2
Reputation: 793
From the getLocation() documentation:
"Due to the asynchronous nature of native event handling, this method can return outdated values (for instance, after several calls of setLocation() in rapid succession). For this reason, the recommended method of obtaining a component's position is within java.awt.event.ComponentListener.componentMoved(), which is called after the operating system has finished moving the component."
Maybe try this.
Upvotes: 1