Issue
I was wondering if there is a way to make JavaFX desktop platform independent application window open on currently active screen, While working on a sample JavaFX application from tutorial.
I am using two monitor system and it would be great if there is a way to make the tool open on the active screen instead of the primary screen each time.
So far I was able to learn setting custom XY location on screen to open the application window but this uses the primary desktop monitor.
More or less looking for centering the window on the screen where mouse cursor is present the moment application starts.
Update:
It is something that can be achieved in Windows Forms C# by setting Form.StartPosition property. Basically telling the application to start from or open on the desktop screen on which the user is currently working or looking at.
Solution
Thanks to @galovics and @Rafael Guillen for hints 1 and 2, I was able to work around this problem.
It is just a try and not the final answer but would like to share the fairly working piece of code to give an idea. I have tested it on Windows and Ubuntu, worked pretty well. FYI I am still just learning JavaFX.
The Below code centers my non-re-sizable JavaFX application window to the active display or monitor screen at start-up.
Note: This only works if you have fixed predefined window size like in my case. Otherwise JavaFX calculates window size after Stage.show()
, and then we can not get Width and Height before show()
method. It returns NaN
. Read comments in class about how to use this in that case.
/*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package Window_On_ActiveScreen;
import java.awt.HeadlessException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.util.List;
import javafx.geometry.Rectangle2D;
import javafx.stage.Screen;
/**
* X-Y position of a Window on active screen at startup if more than one screen.
* Note: This works smooth only if the outer most AnchorPane size is fixed at
* design time. This is because, if the size is not fixed JavaFX calculates
* Window size after Stage.show() method. If the pref size is fixed, then use
* this class in WindowEvent.WINDOW_SHOWING event, or if the pref size is set to
* USE_COMPUTED_SIZE then use it in WindowEvent.WINDOW_SHOWN event (this will
* give a quick splash Window though). Feel free to improve and share this code.
* I am new to JavaFX so tired what I know so far. Tested on Windows but need
* more attention to Linux and Mac
*
* @author
*/
public class StartUpLocation {
private double xPos = 0;
private double yPos = 0;
/**
* Get Top Left X and Y Positions for a Window to centre it on the
* currently active screen at application startup
* @param windowWidth - Window Width
* @param windowHeight - Window Height
*/
public StartUpLocation(double windowWidth, double windowHeight) {
// Get X Y of start-up location on Active Screen
// simple_JavaFX_App
try {
// Get current mouse location, could return null if mouse is moving Super-Man fast
Point p = MouseInfo.getPointerInfo().getLocation();
// Get list of available screens
List<Screen> screens = Screen.getScreens();
if (p != null && screens != null && screens.size() > 1) {
// Screen bounds as rectangle
Rectangle2D screenBounds;
// Go through each screen to see if the mouse is currently on that screen
for (Screen screen : screens) {
screenBounds = screen.getVisualBounds();
// Trying to compute Left Top X-Y position for the Application Window
// If the Point p is in the Bounds
if (screenBounds.contains(p.x, p.y)) {
// Fixed Size Window Width and Height
xPos = screenBounds.getMinX() + ((screenBounds.getMaxX() - screenBounds.getMinX() - windowWidth) / 2);
yPos = screenBounds.getMinY() + ((screenBounds.getMaxY() - screenBounds.getMinY() - windowHeight) / 2);
return;
}
}
}
} catch (HeadlessException headlessException) {
// Catch and report exceptions
headlessException.printStackTrace();
}
}
/**
* @return the top left X Position of Window on Active Screen
*/
public double getXPos() {
return xPos;
}
/**
* @return the top left Y Position of Window on Active Screen
*/
public double getYPos() {
return yPos;
}
}
Now, set Stage
with these X and Y positions if not zero or just set centerOnScreen
It is important to check this here because if the mouse is moving too fast, the point p may return null, so does rest of the calculations or in case of any exceptions as well.
// If Outer most AnchorPane pref size is fixed then use it in this event
// Else otherwise use the handleWindowShownEvent(WindowEvent event)
public void handleWindowShowingEvent(WindowEvent event) {
Stage stage = (Stage) event.getSource();
// Get X Y of start-up location on Active Screen
StartUpLocation startUpLoc = new StartUpLocation(mainWindowAnchorPane.getPrefWidth(), mainWindowAnchorPane.getPrefHeight());
double xPos = startUpLoc.getXPos();
double yPos = startUpLoc.getYPos();
// Set Only if X and Y are not zero and were computed correctly
if (xPos != 0 && yPos != 0) {
stage.setX(xPos);
stage.setY(yPos);
} else {
stage.centerOnScreen();
}
}
Feel free to suggest improvements or any mistakes here.
Update: Added as a generic method in a class.
Answered By - Indigo
Answer Checked By - Senaida (JavaFixing Volunteer)