簡體   English   中英

查找子組件相對於其父面板的位置

[英]Finding position of children Components relative to its parent panel

我正在使用一個 java 程序創建背景圖像,我將其上傳到站點以用於顯示數據。 圖像基於創建獨特視圖和數據點的參數,我可以將其上傳到服務器。

在網站上,我添加了項目以在屏幕上的特定位置顯示數據。 我已經做到了,所以我的 java 程序可以創建背景和數據點,但我必須通過找到正確的位置並在我進行時配置它們來手動配置數據點的位置。

我想在我的 java 程序的父面板中找出特定標簽和面板的相同位置,以便我可以存儲這些點並稍后使用它們為我的數據點生成位置,以便將來可以自動化。

我的背景結構是這樣的

Frame - 包含一個 JTabbedPane,可在 4-10 個不同的面板之間切換。

每個選項卡面板都是成為背景的主面板。

在每個面板內有多個子面板,這些子面板使用 GridbagLayout 進行組織。

每個子面板都可以有自己的面板或標簽,這些面板或標簽是我希望記錄的位置。

這是一張圖片,顯示了其中一個面板的示例。 紅色框是我希望獲得位置的標簽的位置。

圖片

我嘗試使用此代碼查找位置並將它們放在標簽上,但位置始終為 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);
            }
        }
    }

}

這會在我的更新結束時調用該函數

mainPanel.revalidate();
mainPanel.repaint();
positions(mainPanel);

更新。 我從我的框架類調用了上述函數,該函數更新選項卡式窗格上的每個面板,然后將其打包,然后調用該函數。

輸出

正如您所看到的,位置是相對於它的包含標簽的面板,而不是包含所有子面板的面板。

代替

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

在 Frame 上調用pack()方法后調用您的位置方法。

從 getLocation() 文檔:

“由於本機事件處理的異步特性,此方法可能會返回過時的值(例如,在快速連續多次調用 setLocation() 之后)。因此,推薦的獲取組件位置的方法是在 java.awt 中.event.ComponentListener.componentMoved(),在操作系統完成組件移動后調用。”

也許試試這個。

使用 Oliver Watkins 在打包后調用我的方法的建議,我能夠使用它來幫助獲得我的最終解決方案。 由於 jlabel 位於面板內的面板內,因此我必須獲取面板相對於其父面板的位置。 這是我使用的代碼。

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

}

我不得不用空布局手動定位東西。 然后機器人需要在我的上下文中進行糾正。 需要所有組件的 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM