查找子组件相对于其父组件的位置

时间:2016-01-26 14:00:36

标签: java swing

我正在使用java程序创建背景图像,我上传到站点以用于显示数据。这些图像基于创建独特视图和数据点的参数,我可以将其上传到服务器。

在网站上,我添加了项目以显示屏幕上特定位置的数据。我已经做到了,所以我的java程序可以创建背景和数据点,但我必须通过找到正确的位置并按照我的方式配置来手动配置数据点的位置。

我想在我的java程序的父面板中找出特定标签和面板的相同位置,这样我就可以存储这些点并在以后使用它们为我的数据点生成位置,以便将来可以自动化

我的背景结构是这样的

帧 - 保持JTabbedPane,可在4-10个不同的面板之间切换。

每个tabbedpane面板是成为背景的主面板。

在每个面板中,有多个子面板,使用GridbagLayout进行组织。

每个子面板都可以有自己的面板或标签,这些面板或标签是我希望记录的位置。

这是显示其中一个面板的示例的图片。红色框是我想要获得位置的标签的位置。

Pic

我尝试使用此代码查找位置并将其放在标签上,但位置始终为0,0

$scope.options = {
            chart: {
                ...
                color: d3.scale.category20(),

这会在我的更新结束时调用该函数

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

}

更新。我从我的frame类调用了上面的函数,它更新选项卡式窗格上的每个面板,然后打包它,然后调用该函数。

Output

正如您所看到的,位置是相对于包含标签的面板,而不是包含所有子面板的面板。

5 个答案:

答案 0 :(得分:3)

而不是

if (((JLabel) p).getText().isEmpty()) {
    Point spot = ((JLabel) p).getLocation();
    ((JLabel) p).setText(spot.toString());
}

如果你想要相对于主面板的位置,你应该这样做:

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

这基本上会将每个JLabel(位于if内)的坐标添加到其所有父项的坐标,一直到mainPanel

答案 1 :(得分:2)

在您的相框上调用 pack()方法后,请调用位置方法。

答案 2 :(得分:1)

来自getLocation()文档:

  

“由于本机事件处理的异步性质,此方法可以返回过时的值(例如,在快速连续几次调用setLocation()之后)。因此,建议的获取组件位置的方法是在java.awt.event.ComponentListener.componentMoved(),在操作系统完成组件移动后调用。“

也许试试这个。

答案 3 :(得分:1)

使用Oliver Watkins关于在打包后调用我的方法的建议我能够使用它来帮助我获得最终解决方案。由于jlabels位于面板内部的面板内,因此我必须获得面板相对于其父面板的位置。这是我使用的代码。

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

}

答案 4 :(得分:0)

我必须用空布局手动放置东西。然后,在我的上下文中,机器人需要更正。需要所有组件的X和Y位置。我想出了下一个解决方案。从构造函数开始时,“开始”不能是组件本身,而可以是父组件。

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