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

时间:2012-05-03 09:13:13

标签: java swing popupmenu multiple-monitors

我想根据打开菜单的按钮的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 个答案:

答案 0 :(得分:5)

我使用第二个屏幕的边界得到了一个解决方案,这很简单:

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 :(得分:1)

通常当你调用“getLocationOnScreen()”时,它会获得组件“this”的位置(从代码中我不太明白“this”是谁)。

也许您可以尝试使用“button.getLocationOnScreen()”来获取按钮的位置。

答案 2 :(得分: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);
    }
}