簡體   English   中英

position 如何相對於 JFrame 中的 JPanel 的 JDialog

[英]how position a JDialog relative to a JPanel within a JFrame

下面是一些代碼,顯示了我的問題的本質。 我展示了一個包含黃色和綠色JPanelJFrame 這是擴展JPanel並實現Mouselistener的同一 class 的兩個對象。

我想要的是,如果用戶在任一面板上單擊鼠標右鍵,則會在鼠標位置彈出一個JDialog 唉,它沒有,我根本不知道如何獲得正確的行為(在嘗試了很多事情之后)。 你能幫助我嗎?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class DialogPositioning extends JFrame {
    public DialogPositioning() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add two silly panels, then show this JFrame object
        add(new NonsensePanel(Color.YELLOW), BorderLayout.NORTH);
        add(new NonsensePanel(Color.GREEN), BorderLayout.CENTER);
        pack();
        setVisible(true);
    }

    private class NonsensePanel extends JPanel implements MouseListener {
        NonsensePanel(Color bgColor) {
            setPreferredSize(new Dimension(200,200));
            setBackground(bgColor);
            addMouseListener(this);
        }

        @Override
        public void mousePressed(MouseEvent e) {
            if (SwingUtilities.isRightMouseButton(e)) {
                new NonsenseDialog(this, e.getX(), e.getY()); //popup a home-made JDialog at mouse position
            }
        }

        @Override
        public void mouseClicked(MouseEvent e) {}

        @Override
        public void mouseReleased(MouseEvent e) {}

        @Override
        public void mouseEntered(MouseEvent e) {}

        @Override
        public void mouseExited(MouseEvent e) {}
    }

    private class NonsenseDialog extends JDialog {
        NonsenseDialog(Component c, int x, int y) {
            //Add a simple, emmpty panel to this JDialog so that there is something to see, then show this JDialog at the x,y position relative to Component c
            JPanel pnl = new JPanel();
            pnl.setPreferredSize(new Dimension(100, 100));
            add(pnl);

            pack();
            setModal(true);
            setLocationRelativeTo(c); //Should ensure the dialog pops up at posn x,y relative to the top/left corner of ...
            setLocation(x, y);        //... Component c (in our case the yellow or green NonsensePanel objects). DOES NOT WORK???
            setVisible(true);
        }
    }

    public static void main(String[] args) {
        new DialogPositioning();
    }
}

MouseEventgetPoint()方法將返回相對於面板的點。

setLocation(...)方法設置JDialog相對於屏幕。

所以你需要將鼠標點轉換為屏幕位置。

我會更改您的 NonsenseDialog 以接收鼠標點作為參數(而不是單獨的 x/y 值)。

因此,您將使用MouseEventgetPoint()方法傳遞給您的 class。

然后在您的 class 的構造函數中,您可以使用:

Point location = SwingUtilities.convertPointToScreen(...);
setLocation( location );

編輯:您應該使用 camickr 的答案,因為它是更好的解決方案。

您在這里遇到的問題是, e.getX()e.getY()返回的坐標是相對於您單擊的相應JPanel的。 但是當您將這些坐標傳遞到您的JDialog並將它們與setLocation(x, y)一起使用時,這些坐標將相對於您的屏幕。

您缺少原始坐標和目標坐標之間的映射。

如果您想保留自定義對話框而不使用例如JPopupMenu (免費提供此功能),您可以復制JPopupMenu#show()處理此問題的方式。 (見這里

對於您的示例,使用上面鏈接中的代碼,對NonsenseDialog的更改應如下所示:

private class NonsenseDialog extends JDialog {
    NonsenseDialog(Component c, int x, int y) {
        // code taken from jpopupmenu#show
        Point invokerOrigin;
        if (c != null) {
            invokerOrigin = c.getLocationOnScreen();
            // To avoid integer overflow
            long lx, ly;
            lx = ((long) invokerOrigin.x) + ((long) x);
            ly = ((long) invokerOrigin.y) + ((long) y);
            if (lx > Integer.MAX_VALUE)
                lx = Integer.MAX_VALUE;
            if (lx < Integer.MIN_VALUE)
                lx = Integer.MIN_VALUE;
            if (ly > Integer.MAX_VALUE)
                ly = Integer.MAX_VALUE;
            if (ly < Integer.MIN_VALUE)
                ly = Integer.MIN_VALUE;
            setLocation((int) lx, (int) ly);
        } else {
            setLocation(x, y);
        }
        // your code here
        setVisible(true);
    }
}

它的作用是,它從您單擊的組件(您的JPanel )中獲取坐標,並將您傳遞給對話框的坐標(相對於面板的坐標)添加,然后使用生成的坐標來設置對話框的位置。 使用這種方法,您的對話框應該會在右鍵單擊的原點彈出。

暫無
暫無

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

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