Show JFrame in a specific screen in dual monitor configuration
I have a dual monitor config and I want to run my开发者_开发知识库 GUI in a specific monitor if it is found. I tried to create my JFrame
window passing a GraphicConfiguration
object of my screen device, but it doesn't work, frame still display on the main screen.
How can I set the screen where my frame must be displayed?
public static void showOnScreen( int screen, JFrame frame )
{
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
if( screen > -1 && screen < gs.length )
{
gs[screen].setFullScreenWindow( frame );
}
else if( gs.length > 0 )
{
gs[0].setFullScreenWindow( frame );
}
else
{
throw new RuntimeException( "No Screens Found" );
}
}
I have modified @Joseph-gordon's answer to allow for a way to achieve this without forcing full-screen:
public static void showOnScreen( int screen, JFrame frame ) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd = ge.getScreenDevices();
if( screen > -1 && screen < gd.length ) {
frame.setLocation(gd[screen].getDefaultConfiguration().getBounds().x, frame.getY());
} else if( gd.length > 0 ) {
frame.setLocation(gd[0].getDefaultConfiguration().getBounds().x, frame.getY());
} else {
throw new RuntimeException( "No Screens Found" );
}
}
In this code I am assuming getDefaultConfiguration()
will never return null. If that is not the case then someone please correct me. But, this code works to move your JFrame
to the desired screen.
I have modified @Joseph-gordon and @ryvantage answer to allow for a way to achieve this without forcing full-screen, fixed screen configuration position and center it on select screen:
public void showOnScreen(int screen, JFrame frame ) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd = ge.getScreenDevices();
int width = 0, height = 0;
if( screen > -1 && screen < gd.length ) {
width = gd[screen].getDefaultConfiguration().getBounds().width;
height = gd[screen].getDefaultConfiguration().getBounds().height;
frame.setLocation(
((width / 2) - (frame.getSize().width / 2)) + gd[screen].getDefaultConfiguration().getBounds().x,
((height / 2) - (frame.getSize().height / 2)) + gd[screen].getDefaultConfiguration().getBounds().y
);
frame.setVisible(true);
} else {
throw new RuntimeException( "No Screens Found" );
}
}
A much cleaner solution after reading the docs for JFrame.setLocationRelativeTo Display on screen 2
public void moveToScreen() {
setVisible(false);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = ge.getScreenDevices();
int n = screens.length;
for (int i = 0; i < n; i++) {
if (screens[i].getIDstring().contentEquals(settings.getScreen())) {
JFrame dummy = new JFrame(screens[i].getDefaultConfiguration());
setLocationRelativeTo(dummy);
dummy.dispose();
}
}
setVisible(true);
}
This function can be used to switch application window between screens
Please Refer to GraphicsDevice API, you have a good example there.
With everyone chipping in with their own flavors, based on other flavors, I add mine because the others locked you in with regards to positioning of the window on the selected screen.
It is simply the best. It allows you to set the location on the other screen as well.
public void setLocation( int screen, double x, double y ) {
GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] d = g.getScreenDevices();
if ( screen >= d.length ) {
screen = d.length - 1;
}
Rectangle bounds = d[screen].getDefaultConfiguration().getBounds();
// Is double?
if ( x == Math.floor(x) && !Double.isInfinite(x) ) {
x *= bounds.x; // Decimal -> percentage
}
if ( y == Math.floor(y) && !Double.isInfinite(y) ) {
y *= bounds.y; // Decimal -> percentage
}
x = bounds.x + x;
y = jframe.getY() + y;
if ( x > bounds.x) x = bounds.x;
if ( y > bounds.y) y = bounds.y;
// If double we do want to floor the value either way
jframe.setLocation((int)x, (int)y);
}
Example:
setLocation(2, 200, 200);
Even allows you to pass in a percentage for the screen position!
setLocation(2, 0.5, 0); // Place on right edge from the top down if combined with setSize(50%, 100%);
screen must be larger than 0, which I am sure is a tough requirement!
To place on last, simply call with Integer.MAX_VALUE.
My experience is with extending desktops across multiple monitors, versus configuring the monitors as separate (X11) displays. If that's not what you want to do, this won't apply.
And my solution was a bit of a hack: I called Toolkit.getScreenSize()
, determined if I was in a multi-monitor situation (by comparing the height to the width and assuming that width > twice height indicated multi-monitor), then setting the initial X and Y position of the frame.
based on @ryvantage answer, I improved it so it is displayed in the center of the screen:
private static void showOnScreen( int screen, Window frame ) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd = ge.getScreenDevices();
GraphicsDevice graphicsDevice;
if( screen > -1 && screen < gd.length ) {
graphicsDevice = gd[screen];
} else if( gd.length > 0 ) {
graphicsDevice = gd[0];
} else {
throw new RuntimeException( "No Screens Found" );
}
Rectangle bounds = graphicsDevice.getDefaultConfiguration().getBounds();
int screenWidth = graphicsDevice.getDisplayMode().getWidth();
int screenHeight = graphicsDevice.getDisplayMode().getHeight();
frame.setLocation(bounds.x + (screenWidth - frame.getPreferredSize().width) / 2,
bounds.y + (screenHeight - frame.getPreferredSize().height) / 2);
frame.setVisible(true);
}
For me worked well also (supposing left monitor has size 1920x1200):
A) set on left monitor on some exact position:
newFrame.setBounds(200,100,400,200)
B) set on right monitor on some exact position:
newFrame.setBounds(2000,100,200,100)
C) set on left monitor maximized:
newFrame.setBounds(200,100,400,200)
newFrame.setExtendedState(JFrame.MAXIMIZED_BOTH)
D) set on right monitor maximized
newFrame.setBounds(2000,100,200,100)
newFrame.setExtendedState(JFrame.MAXIMIZED_BOTH)
Many of the solutions here works for extended displays. If you are using separate displays just pass the graphics configuration object of the desired graphics device to the constructor of jframe or jdialog.
Vickys answer contains the right pointer. It is new JFrame(GraphicsConfiguration gc) that does it.
You can do it like that:
GraphicsDevice otherScreen = getOtherScreen(this);
JFrame frameOnOtherScreen = new JFrame(otherScreen.getDefaultConfiguration());
private GraphicsDevice getOtherScreen(Component component) {
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
if (graphicsEnvironment.getScreenDevices().length == 1) {
// if there is only one screen, return that one
return graphicsEnvironment.getScreenDevices()[0];
}
GraphicsDevice theWrongOne = component.getGraphicsConfiguration().getDevice();
for (GraphicsDevice dev : graphicsEnvironment.getScreenDevices()) {
if (dev != theWrongOne) {
return dev;
}
}
return null;
}
If u want to set it to center of left screen:
int halfScreen = (int)(screenSize.width/2);
frame.setLocation((halfScreen - frame.getSize().width)/2, (screenSize.height - frame.getSize().height)/2);
If u want to set it to center of right screen:
int halfScreen = (int)(screenSize.width/2);
frame.setLocation((halfScreen - frame.getSize().width)/2 + halfScreen, (screenSize.height - frame.getSize().height)/2);
精彩评论