简体   繁体   English

position 如何相对于 JFrame 中的 JPanel 的 JDialog

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

Below is some code that shows the essence of my issue.下面是一些代码,显示了我的问题的本质。 I show a JFrame containing a yellow and a green JPanel .我展示了一个包含黄色和绿色JPanelJFrame These are two objects of the same class that extends JPanel and implements Mouselistener .这是扩展JPanel并实现Mouselistener的同一 class 的两个对象。

What I want is that, if the user right mouse clicks on either panel, a JDialog pops up at the mouse location.我想要的是,如果用户在任一面板上单击鼠标右键,则会在鼠标位置弹出一个JDialog Alas, it doesn't, and I simply cannot find out how to get the correct behaviour (after trying loads of things).唉,它没有,我根本不知道如何获得正确的行为(在尝试了很多事情之后)。 Can you help me?你能帮助我吗?

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

The getPoint() method of the MouseEvent will return the point that is relative to the panel. MouseEventgetPoint()方法将返回相对于面板的点。

The setLocation(...) method sets the JDialog relative to the screen. setLocation(...)方法设置JDialog相对于屏幕。

So you need to convert the mouse point to the screen location.所以你需要将鼠标点转换为屏幕位置。

I would change your NonsenseDialog to receive the mouse Point as a parameter (instead of the separate x/y values).我会更改您的 NonsenseDialog 以接收鼠标点作为参数(而不是单独的 x/y 值)。

So you would use the getPoint() method of the MouseEvent to pass to your class.因此,您将使用MouseEventgetPoint()方法传递给您的 class。

Then in the constructor of your class you can use:然后在您的 class 的构造函数中,您可以使用:

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

Edit: You should use camickr's answer, as it is the better solution.编辑:您应该使用 camickr 的答案,因为它是更好的解决方案。

The issue you are having here is, that the coordinates returned by e.getX() and e.getY() are relative to the corresponding JPanel where you clicked.您在这里遇到的问题是, e.getX()e.getY()返回的坐标是相对于您单击的相应JPanel的。 But when you pass these coordinates into your JDialog and use them with setLocation(x, y) , these coordinates will be relative to your screen.但是当您将这些坐标传递到您的JDialog并将它们与setLocation(x, y)一起使用时,这些坐标将相对于您的屏幕。

You are missing a mapping between your original coordinates and your target coordinates.您缺少原始坐标和目标坐标之间的映射。

If you want to keep the custom dialog and not use eg JPopupMenu (which provides this for free), you can just copy the way that JPopupMenu#show() handles this.如果您想保留自定义对话框而不使用例如JPopupMenu (免费提供此功能),您可以复制JPopupMenu#show()处理此问题的方式。 (See here ) (见这里

For your example, using the code from the link above, the changes to the NonsenseDialog should look like the following:对于您的示例,使用上面链接中的代码,对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);
    }
}

What this does is, it takes the coordinates from the component you clicked (your JPanel ) and adds the coordinates you passed to the dialog (the coordinates relative to the panel), then uses the resulting coordinates to set the location of the dialog.它的作用是,它从您单击的组件(您的JPanel )中获取坐标,并将您传递给对话框的坐标(相对于面板的坐标)添加,然后使用生成的坐标来设置对话框的位置。 With this approach, your dialog should pop up at the origin of the right click.使用这种方法,您的对话框应该会在右键单击的原点弹出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM