获取组件在当前监视器上的位置

3
我希望能根据打开菜单的按钮的y位置设置JPopupMenu的位置。 我的代码在第一个显示器上运行良好,但在第二个显示器上失败,因为它具有不同的高度。 问题在于getLocationOnScreen()相对于主屏幕提供位置,而不是组件所在的实际屏幕。
我的代码是:
// screenSize represents the size of the screen where the button is
// currently showing
final Rectangle screenSize = dateButton.getGraphicsConfiguration().getBounds();

final int yScreen = screenSize.height;
int preferredY;

// getLocationOnScreen does always give the relative position to the main screen
if (getLocationOnScreen().y + dateButton.getHeight() + datePopup.getPreferredSize().height > yScreen) {
  preferredY = -datePopup.getPreferredSize().height;
} else {
  preferredY = getPreferredSize().height;
}

datePopup.show(DateSpinner.this, 0, preferredY);

如何获取组件在其实际监视器上的位置?

3个回答

7
我有一个关于这个问题的解决方案,使用第二屏幕的边界来实现,非常简单:
public static Point getLocationOnCurrentScreen(final Component c) {
  final Point relativeLocation = c.getLocationOnScreen();

  final Rectangle currentScreenBounds = c.getGraphicsConfiguration().getBounds();

  relativeLocation.x -= currentScreenBounds.x;
  relativeLocation.y -= currentScreenBounds.y;

  return relativeLocation;
}

感谢您的回答!

1
如果副屏幕在相反的位置怎么办?如果主屏幕和副屏幕交换了怎么办? - Stefan
应该是 "+=" 吧? - Andreas Scharf

1
这是一个小的示例,展示如何将元素相对于另一个元素定位。它在按钮下方显示弹出菜单,并在其左侧显示JDialog。我在一个多屏幕环境中进行了测试,其中辅助屏幕位于主屏幕右侧。
此外,使用getSize(),getWidth()和getHeight()方法代替getPreferredSize()。getSize,getWidth和getHeight返回组件的实际尺寸,而getPreferredSize()仅是指示LayoutManager组件希望具有的尺寸。
如果您使用方法JPopupMenu.show(),请确保使用相对于调用者组件的坐标和大小。
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

public class Test2 {

    public static void main(String[] args) {

        final JFrame frame = new JFrame();
        final JButton button = new JButton("Hello");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JPopupMenu popupMenu = new JPopupMenu();
                popupMenu.add(new JMenuItem("Some test"));
                System.err.println(button.getLocationOnScreen());
                popupMenu.show(button, 0, button.getHeight());
                JDialog dialog = new JDialog(frame);
                dialog.setSize(100, 30);
                Point locationOnScreen = button.getLocationOnScreen();
                locationOnScreen.x += button.getWidth();
                dialog.setLocation(locationOnScreen);
                dialog.setVisible(true);
            }
        });
        frame.addComponentListener(new ComponentListener() {

            @Override
            public void componentShown(ComponentEvent e) {

            }

            @Override
            public void componentResized(ComponentEvent e) {
                info(button);
            }

            private void info(final JButton button) {
                if (button.isShowing()) {
                    System.err.println(button.getLocationOnScreen());
                    System.err.println(button.getGraphicsConfiguration().getBounds());
                }
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                info(button);
            }

            @Override
            public void componentHidden(ComponentEvent e) {

            }
        });
        button.setPreferredSize(new Dimension(200, 60));
        frame.add(button);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }
}

1
通常当您调用“getLocationOnScreen()”时,它会获取组件“this”的位置(从代码中我不太理解“this”是谁)。
也许您可以尝试使用“button.getLocationOnScreen()”来获取按钮的位置。

这被称为包含按钮的面板内部。 - Stephan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接