Related
I'm trying to run two Kinect V1 cameras simultaneously in Processing 3. I have gotten to a solution that is not sustainable, and am I trying to make something more stable/reliable.
At the moment, whenever I try to run both cameras simultaneously on a single sketch, I am hit with the error
"Could not claim interface on camera: -3
Failed to open camera subdevice or it is not disabled.Failed to open motor subddevice or it is not disabled.Failed to open audio subdevice or it is not disabled.There are no kinects, returning null"
One camera opens, the other does not. It is not always consistent which camera opens, which leads me to believe there's something tripping over permissions after the objects are created, or when the second object is initialized.
My code is as such
import SimpleOpenNI.*;
import org.openkinect.freenect.*;
import org.openkinect.freenect2.*;
import org.openkinect.processing.*;
import org.openkinect.tests.*;
//Imported libraries
//Some might be unnecessary but I don't have time to check
//Better safe than sorry, maybe I'll delete later
Kinect kinect;
Kinect kinect2;
PImage depthImage;
PImage depthImage2;
//Set depth threshold
float minDepth = 996;
float maxDepth = 2493;
float iWidth1 = 0;
float iHeight1 = 0;
float iWidth2 = 0;
float iHeight2 = 0;
//Double check for the number of devices, mostly for troubleshooting
int numDevices = 0;
//control which device is being controlled (in case I want device control)
int deviceIndex = 0;
void setup() {
//set Arbitrary size
size(640, 360);
//Set up window to resize, need to figure out how to keep things centered
surface.setResizable(true);
//not necessary, but good for window management. Window label
surface.setTitle("KINECT 1");
//get number of devices, print to console
numDevices = Kinect.countDevices();
println("number of V1 Kinects = "+numDevices);
//set up depth for the first kinect tracking
kinect = new Kinect(this);
kinect.initDepth();
//Blank Image
depthImage = new PImage(kinect.width, kinect.height);
//set up second window
String [] args = {"2 Frame Test"};
SecondApplet sa = new SecondApplet();
PApplet.runSketch(args, sa);
}
//Draw first window's Kinect Threshold
void draw () {
if ((width/1.7778) < height) {
iWidth1 = width;
iHeight1 = width/1.7778;
} else {
iWidth1 = height*1.7778;
iHeight1 = height;
}
//Raw Image
image(kinect.getDepthImage(), 0, 0, iWidth1, iHeight1);
//Threshold Equation
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImage.pixels[i] = color(255);
} else {
depthImage.pixels[i] = color(1);
}
}
}
public class SecondApplet extends PApplet {
public void settings() {
//arbitrary size
size(640, 360);
kinect2 = new Kinect(this);
kinect2.initDepth();
//Blank Image
depthImage2 = new PImage(kinect2.width, kinect2.height);
}
void draw () {
if ((width/1.7778) < height) {
iWidth2 = width;
iHeight2 = width/1.7778;
} else {
iWidth2 = height*1.7778;
iHeight2 = height;
}
image(kinect2.getDepthImage(), 0, 0, iWidth2, iHeight2);
surface.setResizable(true);
surface.setTitle("KINECT 2");
int[] rawDepth2 = kinect2.getRawDepth();
for (int i=0; i < rawDepth2.length; i++) {
if (rawDepth2[i] >= minDepth && rawDepth2[i] <= maxDepth) {
depthImage2.pixels[i] = color(255);
} else {
depthImage2.pixels[i] = color(1);
}
}
}
}
Curiously, the code returns a confirmation that there are two kinect devices connected in the console. For some reason, it cannot access both at the same time.
I'm not a very experienced code, so this code might look amateur. Open to feedback on other parts, but really just looking to solve this problem.
This code returns the error pasted above when there are two Kinect V1's connected to the computer.
Running Mac OS11.6.8 on an Intel MacBook Pro
Using Daniel Schiffman's OpenKinect for Processing as a starting point for the code.
I've run a successful iteration of this code with a slimmed down version of Daniel Schiffman's Depth Threshold example.
import org.openkinect.freenect.*;
import org.openkinect.processing.*;
Kinect kinect;
// Depth image
PImage depthImg;
// Which pixels do we care about?
// These thresholds can also be found with a variaty of methods
float minDepth = 996;
float maxDepth = 2493;
// What is the kinect's angle
float angle;
void setup() {
size(1280, 480);
kinect = new Kinect(this);
kinect.initDepth();
angle = kinect.getTilt();
// Blank image
depthImg = new PImage(kinect.width, kinect.height);
}
void draw() {
// Draw the raw image
image(kinect.getDepthImage(), 0, 0);
// Calibration
//minDepth = map(mouseX,0,width, 0, 4500);
//maxDepth = map(mouseY,0,height, 0, 4500);
// Threshold the depth image
int[] rawDepth = kinect.getRawDepth();
for (int i=0; i < rawDepth.length; i++) {
if (rawDepth[i] >= minDepth && rawDepth[i] <= maxDepth) {
depthImg.pixels[i] = color(255);
} else {
depthImg.pixels[i] = color(0);
}
}
// Draw the thresholded image
depthImg.updatePixels();
image(depthImg, kinect.width, 0);
//Comment for Calibration
fill(0);
text("TILT: " + angle, 10, 20);
text("THRESHOLD: [" + minDepth + ", " + maxDepth + "]", 10, 36);
//Calibration Text
//fill(255);
//textSize(32);
//text(minDepth + " " + maxDepth, 10, 64);
}
Using this code, I was able to get both cameras operating using the following process:
Connect a single Kinect v1 to the computer
Open and run the above code
Duplicate the sketch file
Connect the second Kinect V1 to the computer
Open and run the duplicated sketch of the same code
This worked for my purposes and remained stable for an extended period of time. However, this isn't a sustainable solution if anyone other than me wants to utilize this program.
Any help with this problem would be greatly appreciated
How can one get the screen resolution (width x height) in pixels?
I am using a JFrame and the java swing methods.
You can get the screen size with the Toolkit.getScreenSize() method.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
On a multi-monitor configuration you should use this :
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
If you want to get the screen resolution in DPI you'll have to use the getScreenResolution() method on Toolkit.
Resources :
javadoc - Toolkit.getScreenSize()
Java bug 5100801- Toolkit.getScreenSize() does not return the correct dimension on multimon, linux
This code will enumerate the graphics devices on the system (if multiple monitors are installed), and you can use that information to determine monitor affinity or automatic placement (some systems use a little side monitor for real-time displays while an app is running in the background, and such a monitor can be identified by size, screen colors, etc.):
// Test if each monitor will support my app's window
// Iterate through each monitor and see what size each is
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
Dimension mySize = new Dimension(myWidth, myHeight);
Dimension maxSize = new Dimension(minRequiredWidth, minRequiredHeight);
for (int i = 0; i < gs.length; i++)
{
DisplayMode dm = gs[i].getDisplayMode();
if (dm.getWidth() > maxSize.getWidth() && dm.getHeight() > maxSize.getHeight())
{ // Update the max size found on this monitor
maxSize.setSize(dm.getWidth(), dm.getHeight());
}
// Do test if it will work here
}
This call will give you the information you want.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Here's some functional code (Java 8) which returns the x position of the right most edge of the right most screen. If no screens are found, then it returns 0.
GraphicsDevice devices[];
devices = GraphicsEnvironment.
getLocalGraphicsEnvironment().
getScreenDevices();
return Stream.
of(devices).
map(GraphicsDevice::getDefaultConfiguration).
map(GraphicsConfiguration::getBounds).
mapToInt(bounds -> bounds.x + bounds.width).
max().
orElse(0);
Here are links to the JavaDoc.
GraphicsEnvironment.getLocalGraphicsEnvironment()
GraphicsEnvironment.getScreenDevices()
GraphicsDevice.getDefaultConfiguration()
GraphicsConfiguration.getBounds()
These three functions return the screen size in Java. This code accounts for multi-monitor setups and task bars. The included functions are: getScreenInsets(), getScreenWorkingArea(), and getScreenTotalArea().
Code:
/**
* getScreenInsets, This returns the insets of the screen, which are defined by any task bars
* that have been set up by the user. This function accounts for multi-monitor setups. If a
* window is supplied, then the the monitor that contains the window will be used. If a window
* is not supplied, then the primary monitor will be used.
*/
static public Insets getScreenInsets(Window windowOrNull) {
Insets insets;
if (windowOrNull == null) {
insets = Toolkit.getDefaultToolkit().getScreenInsets(GraphicsEnvironment
.getLocalGraphicsEnvironment().getDefaultScreenDevice()
.getDefaultConfiguration());
} else {
insets = windowOrNull.getToolkit().getScreenInsets(
windowOrNull.getGraphicsConfiguration());
}
return insets;
}
/**
* getScreenWorkingArea, This returns the working area of the screen. (The working area excludes
* any task bars.) This function accounts for multi-monitor setups. If a window is supplied,
* then the the monitor that contains the window will be used. If a window is not supplied, then
* the primary monitor will be used.
*/
static public Rectangle getScreenWorkingArea(Window windowOrNull) {
Insets insets;
Rectangle bounds;
if (windowOrNull == null) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
insets = Toolkit.getDefaultToolkit().getScreenInsets(ge.getDefaultScreenDevice()
.getDefaultConfiguration());
bounds = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();
} else {
GraphicsConfiguration gc = windowOrNull.getGraphicsConfiguration();
insets = windowOrNull.getToolkit().getScreenInsets(gc);
bounds = gc.getBounds();
}
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
return bounds;
}
/**
* getScreenTotalArea, This returns the total area of the screen. (The total area includes any
* task bars.) This function accounts for multi-monitor setups. If a window is supplied, then
* the the monitor that contains the window will be used. If a window is not supplied, then the
* primary monitor will be used.
*/
static public Rectangle getScreenTotalArea(Window windowOrNull) {
Rectangle bounds;
if (windowOrNull == null) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
bounds = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();
} else {
GraphicsConfiguration gc = windowOrNull.getGraphicsConfiguration();
bounds = gc.getBounds();
}
return bounds;
}
This is the resolution of the screen that the given component is currently assigned (something like most part of the root window is visible on that screen).
public Rectangle getCurrentScreenBounds(Component component) {
return component.getGraphicsConfiguration().getBounds();
}
Usage:
Rectangle currentScreen = getCurrentScreenBounds(frameOrWhateverComponent);
int currentScreenWidth = currentScreen.width // current screen width
int currentScreenHeight = currentScreen.height // current screen height
// absolute coordinate of current screen > 0 if left of this screen are further screens
int xOfCurrentScreen = currentScreen.x
If you want to respect toolbars, etc. you'll need to calculate with this, too:
GraphicsConfiguration gc = component.getGraphicsConfiguration();
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
Unfortunately Toolkit.getDefaultToolkit() does not help if you have multiple displays, and on Windows it also reports scaled values if you have changed font setting "Scale and Layout" from 100%. For example at 150% font scale my 1920x1080 screen is reported as 1280x720 which (unhelpfully) changes the resolution my app uses.
You can access all details of the screen devices under:
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
// Windows scaled sizes (eg 1280x720 for my case at 150% scaling)
Rectangle bounds = devices[nnn].getDefaultConfiguration().getBounds();
// Display sizes (same as above at 100% scale, 1920x1080 for my case)
DisplayMode dm = devices[nnn].getDefaultConfiguration().getDevice().getDisplayMode();
Rectangle orig = new Rectangle((int)bounds.getX(), (int)bounds.getY(), dm.getWidth(), dm.getHeight());
I use this method which reads the default display modes of each GraphicsDevice to access the original screen position+dimensions, and returns set of rectangles sorted in left->right X position order per screen:
/** Get actual screen display sizes, ignores Windows font scaling, sort left to right */
public static List<Rectangle> getDisplays() {
return Arrays.stream(GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices())
.map(GraphicsDevice::getDefaultConfiguration)
// For scaled sizes use .map(GraphicsConfiguration::getBounds) instead of:
.map(c -> {
var dm = c.getDevice().getDisplayMode();
var bounds = c.getBounds();
return new Rectangle((int)bounds.getX(), (int)bounds.getY(), dm.getWidth(), dm.getHeight());
})
.sorted(Comparator.comparing(Rectangle::getX))
.toList();
}
The above code runs under Windows and WSL. If you wish to have a version which returns the scaled values, just switch the commented out line above.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
framemain.setSize((int)width,(int)height);
framemain.setResizable(true);
framemain.setExtendedState(JFrame.MAXIMIZED_BOTH);
Here is a snippet of code I often use. It returns the full available screen area (even on multi-monitor setups) while retaining the native monitor positions.
public static Rectangle getMaximumScreenBounds() {
int minx=0, miny=0, maxx=0, maxy=0;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
for(GraphicsDevice device : environment.getScreenDevices()){
Rectangle bounds = device.getDefaultConfiguration().getBounds();
minx = Math.min(minx, bounds.x);
miny = Math.min(miny, bounds.y);
maxx = Math.max(maxx, bounds.x+bounds.width);
maxy = Math.max(maxy, bounds.y+bounds.height);
}
return new Rectangle(minx, miny, maxx-minx, maxy-miny);
}
On a computer with two full-HD monitors, where the left one is set as the main monitor (in Windows settings), the function returns
java.awt.Rectangle[x=0,y=0,width=3840,height=1080]
On the same setup, but with the right monitor set as the main monitor, the function returns
java.awt.Rectangle[x=-1920,y=0,width=3840,height=1080]
int resolution =Toolkit.getDefaultToolkit().getScreenResolution();
System.out.println(resolution);
There's many answers but I still feel they're not adequate enough, my approach computes global variables related to the screen size once and also using a single loop of all the monitors:
public final class ScreenArea {
public static final Rectangle RECTANGLE;
public static final int
LEFT, RIGHT,
TOP, BOTTOM,
MIN_WIDTH, MAX_WIDTH,
MIN_HEIGHT, MAX_HEIGHT,
TOTAL_WIDTH, TOTAL_HEIGHT;
static {
// Initialise local vars
int left, right, top, bottom, minWidth, maxWidth, minHeight, maxHeight;
left = top = minWidth = minHeight = Integer.MAX_VALUE;
right = bottom = maxWidth = maxHeight = Integer.MIN_VALUE;
// In a single loop process all bounds
Rectangle bounds;
for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
bounds = device.getDefaultConfiguration().getBounds();
if (left > bounds.x)
left = bounds.x;
if (right < bounds.x + bounds.width)
right = bounds.x + bounds.width;
if (top > bounds.y)
top = bounds.y;
if (bottom < bounds.y + bounds.height)
bottom = bounds.y + bounds.height;
if (minWidth > bounds.width)
minWidth = bounds.width;
if (maxWidth < bounds.width)
maxWidth = bounds.width;
if (minHeight > bounds.height)
minHeight = bounds.height;
if (maxHeight < bounds.height)
maxHeight = bounds.height;
}
TOTAL_WIDTH = right - left;
TOTAL_HEIGHT = bottom - top;
RECTANGLE = new Rectangle(TOTAL_WIDTH, TOTAL_HEIGHT);
// Transfer local to immutable global vars
LEFT = left; RIGHT = right; TOP = top; BOTTOM = bottom;
MIN_WIDTH = minWidth; MAX_WIDTH = maxWidth;
MIN_HEIGHT = minHeight; MAX_HEIGHT = maxHeight;
}
}
Then you can use anytime as is just like this :
System.out.printf("LEFT=%d, ", ScreenArea.LEFT);
System.out.printf("RIGHT=%d%n", ScreenArea.RIGHT);
System.out.printf("TOP=%d, ", ScreenArea.TOP);
System.out.printf("BOTTOM=%d%n", ScreenArea.BOTTOM);
System.out.printf("MIN_WIDTH=%d, ", ScreenArea.MIN_WIDTH);
System.out.printf("MAX_WIDTH=%d%n", ScreenArea.MAX_WIDTH);
System.out.printf("MIN_HEIGHT=%d, ", ScreenArea.MIN_HEIGHT);
System.out.printf("MAX_HEIGHT=%d%n", ScreenArea.MAX_HEIGHT);
System.out.printf("SCREEN_AREA=%s%n", ScreenArea.RECTANGLE);
Which on my dual monitor setup it prints :
LEFT=0, RIGHT=3840
TOP=0, BOTTOM=1080
MIN_WIDTH=1920, MAX_WIDTH=1920
MIN_HEIGHT=1080, MAX_HEIGHT=1080
SCREEN_AREA=java.awt.Rectangle[x=0,y=0,width=3840,height=1080]
int screenResolution = Toolkit.getDefaultToolkit().getScreenResolution();
System.out.println(""+screenResolution);
I am trying to move a JFrame around in Windows using 5 buttons (North, East, South, West, and Centre) At the moment all the current code is in place and it works when using;
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==northButton)
{
setLocation(500,500);
}
} //works
public void actionPerformed(ActionEvent e)
{
if(e.getSource()== northButton)
{
setLocation(north);
}
} //doesn't work
However as part of the task I need to use the Java Toolkit to getScreenSize width and height and using calculations to work out the boundaries of the screen and send 'north' to setLocation() (like above). However, using this method it throws an error "No suitable method found" I'm unsure of how to fix this. The calculation code is below just for north at the moment.
int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
int width = this.getWidth();
int height = this.getHeight();
int north = ((screenWidth - width)/2);
Any help will be greatly appreciated.
Thanks!
Here you are passing two parameters, X and Y:
setLocation(500,500);
Here you are passing one, but which is it? X or Y? If X, where's Y?:
int north = ((screenWidth - width)/2);
setLocation(north);
The compiler is telling you it doesn't have a setLocation() method that takes one parameter. It wants a location in 2D space: that's an X and Y. Probably what you want is:
setLocation(north, 0);
Toolkit.getDefaultToolkit().getScreenSize() returns the full size of the default screen, it does not take into consideration things like task bars or other elements which may occupy space on the desktop which windows should avoid been placed under/over.
A better solution would be to use Toolkit.getDefaultToolkit().getScreenInsets(GraphicsConfiguration) and GraphicsConfiguration#getBounds
public static Rectangle getScreenViewableBounds(Window window) {
return getScreenViewableBounds((Component) window);
}
public static Rectangle getScreenViewableBounds(Component comp) {
return getScreenViewableBounds(getGraphicsDevice(comp));
}
public static Rectangle getScreenViewableBounds(GraphicsDevice gd) {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
if (gd == null) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
gd = ge.getDefaultScreenDevice();
}
if (gd != null) {
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bounds = gc.getBounds();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
}
return bounds;
}
/**
* Attempts to locate the graphics device that the component most likely is
* on.
*
* This calculates the area that the window occupies on each screen deivce and
* returns the one which it occupies the most.
*
* #param comp
* #return
*/
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;
}
The main issue you're having is that there is no such method as setLocation(int)...what would the value int represent any way? x or y position?
You need to pass both the x and y position to setLocation in order for it to work.
Rectangle bounds = getScreenViewableBounds(this); // where this is a reference to your window
int x = bounds.x + ((bounds.width - getWidth()) / 2;
int y = bounds.y;
setLocation(x, y);
For example...
There is a JFrame, when it in a multi-monitor environment, how to display this JFrame in full screen display? For example, now the JFrame is displaying in monitor 1, when it is going to change to full screen display mode,it must be displayed in the monitor 1; if is displaying in monitor 2,when it is going to change to full screen display mode, it must be displayed in
the monitor 2.
Try this,
For Single Screen
Toolkit tool = Toolkit.getDefaultToolkit();
Dimension dim = tool.getScreenSize();
int screenWidth = dim.getWidth();
int screenHeight = dim.getHeight();
For Multiple Screen
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
// Get size of each screen
for (int i=0; i<gs.length; i++) {
DisplayMode dm = gs[i].getDisplayMode();
int screenWidth = dm.getWidth();
int screenHeight = dm.getHeight();
}
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);