Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to figure out on which screen a JDialog is shown

I have a really big application which has multiple dialogs. My task is to make sure that a dialog, which is not completely visible (because the user pulled it out of the visible screen area) is moved back to the center of the screen.

That's no problem when I'm dealing with one screen only. It works just fine ... however, most users of this application have two screens on their desktop ...

When I try to figure out on which screen the dialog is shown and center it on that specific screen, ... well, it actually DOES center, but on the primary screen (which may not be the screen the dialog is shown on).

To show you what my thoughts were so far, here's the code ...

 /**
 * Get the number of the screen the dialog is shown on ...
 */
private static int getActiveScreen(JDialog jd) {
    int screenId = 1;
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice[] gd = ge.getScreenDevices();
    for (int i = 0; i < gd.length; i++) {
        GraphicsConfiguration gc = gd[i].getDefaultConfiguration();
        Rectangle r = gc.getBounds();
        if (r.contains(jd.getLocation())) {
            screenId = i + 1;
        }
    }
    return screenId;
}

/**
* Get the Dimension of the screen with the given id ...
*/
private static Dimension getScreenDimension(int screenId) {
    Dimension d = new Dimension(0, 0);
    if (screenId > 0) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        DisplayMode mode = ge.getScreenDevices()[screenId - 1].getDisplayMode();
        d.setSize(mode.getWidth(), mode.getHeight());
    }
    return d;
}

/**
 * Check, if Dialog can be displayed completely ...
 * @return true, if dialog can be displayed completely
 */
private boolean pruefeDialogImSichtbarenBereich() {
    int screenId = getActiveScreen(this);
    Dimension dimOfScreen = getScreenDimension(screenId);
    int xPos = this.getX();
    int yPos = this.getY();
    Dimension dimOfDialog = this.getSize();
    if (xPos + dimOfDialog.getWidth() > dimOfScreen.getWidth() || yPos + dimOfDialog.getHeight() > dimOfScreen.getHeight()) {
        return false;
    }
    return true;
}

/**
 * Center Dialog...
 */
private void zentriereDialogAufMonitor() {
    this.setLocationRelativeTo(null);
}

While debugging I kind of came across the fact that getActiveScreen() does not seem to work the way i though; it seems to always return 2 (which is kind of crap, since it would mean the dialog is always shown in the second monitor...which of course isn't the truth).

Anyone got any idea how to center my dialog on the screen it is actually shown on?

like image 926
gilaras Avatar asked Aug 28 '12 11:08

gilaras


1 Answers

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.

like image 157
Boann Avatar answered Oct 03 '22 20:10

Boann