How to figure out on which screen a JDialog is shown

ぐ巨炮叔叔 提交于 2019-12-04 04:57:51

Your getActiveScreen method worked, except it used the screen containing the top-left corner of the window. If you use Component.getGraphicsConfiguration() instead, it will give you which screen has the most of the window's pixels. setLocationRelativeTo(null) is no help here because it always uses the primary screen. Here's how to solve it:

static boolean windowFitsOnScreen(Window w) {
    return w.getGraphicsConfiguration().getBounds().contains(w.getBounds());
}

static void centerWindowToScreen(Window w) {
    Rectangle screen = w.getGraphicsConfiguration().getBounds();
    w.setLocation(
        screen.x + (screen.width - w.getWidth()) / 2,
        screen.y + (screen.height - w.getHeight()) / 2
    );
}

Then you can do:

JDialog jd;
...
if (!windowFitsOnScreen(jd)) centerWindowToScreen(jd);

which will center the dialog to the nearest screen (monitor). You might need to make sure the dialog has been initially displayed/positioned first.

I'm not sure how much of this will be of use, but this is the code that I use when trying to determine graphic devices for windows.

I cheat a little, I tend to use Component and allow the utility methods to either find the top level window or use the Component's screen point.

/**
 * Returns the GraphicsDevice that the specified component appears the most on.
 */
public static GraphicsDevice getGraphicsDevice(Component comp) {

    GraphicsDevice device = null;

    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice lstGDs[] = ge.getScreenDevices();

    ArrayList<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length);
    if (comp != null && comp.isVisible()) {
        Rectangle parentBounds = comp.getBounds();

        /*
         * If the component is not a window, we need to find its location on the
         * screen...
         */
        if (!(comp instanceof Window)) {
            Point p = new Point(0, 0);
            SwingUtilities.convertPointToScreen(p, comp);
            parentBounds.setLocation(p);
        }

        for (GraphicsDevice gd : lstGDs) {
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            Rectangle screenBounds = gc.getBounds();
            if (screenBounds.intersects(parentBounds)) {
                lstDevices.add(gd);
            }
        }

        if (lstDevices.size() == 1) {
            device = lstDevices.get(0);
        } else {

            GraphicsDevice gdMost = null;
            float maxArea = 0;
            for (GraphicsDevice gd : lstDevices) {
                int width = 0;
                int height = 0;

                GraphicsConfiguration gc = gd.getDefaultConfiguration();
                Rectangle bounds = gc.getBounds();

                Rectangle2D intBounds = bounds.createIntersection(parentBounds);

                float perArea = (float) ((intBounds.getWidth() * intBounds.getHeight()) / (parentBounds.width * parentBounds.height));
                if (perArea > maxArea) {
                    maxArea = perArea;
                    gdMost = gd;
                }
            }

            if (gdMost != null) {
                device = gdMost;
            }
        }
    }
    return device;
}

/**
 * Returns the GraphicsDevice at the specified point
 */
public static GraphicsDevice getGraphicsDeviceAt(Point pos) {
    GraphicsDevice device = null;
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice lstGDs[] = ge.getScreenDevices();

    List<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length);
    for (GraphicsDevice gd : lstGDs) {

        GraphicsConfiguration gc = gd.getDefaultConfiguration();
        Rectangle screenBounds = gc.getBounds();
        if (screenBounds.contains(pos)) {
            lstDevices.add(gd);
        }
    }

    if (lstDevices.size() > 0) {
        device = lstDevices.get(0);
    }

    return device;
}

/**
 * Returns the Point that would allow the supplied Window to be
 * centered on it's current graphics device.
 * 
 * It's VERY important that the Window be seeded with a location
 * before calling this method, otherwise it will appear on the 
 * device at 0x0
 *
 * @param window
 * @return
 */
public static Point centerOfScreen(Window window) {
    // Try and figure out which window we actually reside on...
    GraphicsDevice gd = getGraphicsDeviceAt(window.getLocation());
    GraphicsConfiguration gc = gd.getDefaultConfiguration();

    Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());
    Rectangle bounds = gc.getBounds();
    Dimension size = bounds.getSize();

    size.width -= (screenInsets.left + screenInsets.right);
    size.height -= (screenInsets.top + screenInsets.bottom);

    int width = window.getWidth();
    int height = window.getHeight();

    int xPos = screenInsets.left + ((size.width - width) / 2);
    int yPos = screenInsets.top + ((size.height - height) / 2);

    return new Point(xPos, yPos);
}

Here's the code used to center location of the window.

  //Center the window
  Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  Dimension frameSize = frame.getSize();
  if (frameSize.height > screenSize.height) {
    frameSize.height = screenSize.height;
  }
  if (frameSize.width > screenSize.width) {
    frameSize.width = screenSize.width;
  }
  frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);

with the frame you can use the dialog as well.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!