Centering an image in an ImageView - imageview

I am currently trying to center an image in an ImageView using JavaFX.
So I load the image in the view :
Image img = new Image("...");
imageView.setImage(img);
and let's suppose the image is huge (2000x3000) and not the ImageView (400x100)
The rendered image will be aligned on the left, and I would like to put in the center of the ImageView :
Is there anyway to perform that ?

So, after days of calculation, I managed to find a good way to do it.
I post it here in case of someone would like to achieve it.
I created a method that only needs access to the imageView :
public void centerImage() {
Image img = imageView.getImage();
if (img != null) {
double w = 0;
double h = 0;
double ratioX = imageView.getFitWidth() / img.getWidth();
double ratioY = imageView.getFitHeight() / img.getHeight();
double reducCoeff = 0;
if(ratioX >= ratioY) {
reducCoeff = ratioY;
} else {
reducCoeff = ratioX;
}
w = img.getWidth() * reducCoeff;
h = img.getHeight() * reducCoeff;
imageView.setX((imageView.getFitWidth() - w) / 2);
imageView.setY((imageView.getFitHeight() - h) / 2);
}
}

Here is an example code that might be a solution for your case:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Test extends Application {
#Override
public void start(Stage primaryStage) {
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/a/a7/Frankenstein's_monster_(Boris_Karloff).jpg");
ImageView imageView = new ImageView();
imageView.setImage(image);
imageView.setPreserveRatio(true);
imageView.setFitWidth(400);
imageView.setFitHeight(300);
BorderPane pane = new BorderPane();
pane.setPrefSize(400, 300);
pane.setCenter(imageView);
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
And the result:

Here's how I would do it
import javafx.geometry.Pos;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
Image img = new Image("...");
imageView imgView = new imageView(img);
HBox hbxImg = new HBox();
hbxImg.setAlignment(Pos.CENTER);
hbxImg.getChildren().add(imgView);
That'll put an image in an empty HBox you can align to the horizontal center of the canvas.

Related

Updating the Width of TextField and VBox when Full screened JavaFX

whenever I try to full screen my application, it doesn't scale. I've made multiple copies of this application trying different methods but none seem to work right.
First attempt: Application was a Parent, it would scale the background but the elements inside wouldn't scale to screen size.
As an update: here is the actual Parent that was made. The layout is the original one I wrote and has no issues when it's windowed. It has a preset WIDTH and HEIGHT but when full screened, The first example picture is what it looks like where the WIDTH of the the TextField doesn't update (since it's preset and not updating to the highest WIDTH of the screen it's running on). There are two parts to this that CAN be fixed when only one is fixed. The displayed Text has a set wrapping length of the console, though it is set by using WIDTH.
Here's what the console looks like when it's windowed:
If I could find a way to change the WIDTH, I'm thinking this can be fixed for both the TextField and the setWrappingWidth().
package application.console;
import application.areas.startingArea.SA;
import application.areas.vanguardForest.VFCmds;
import application.areas.vanguardForest.VFNavi;
import application.areas.vanguardForest.VFPkups;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Parent;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.control.TextField;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class Ce extends Region {
public static boolean fullscreen = false;
public static double WIDTH = 990;
// 990;
// Screen.getPrimary().getBounds().getMaxX();
public static double HEIGHT = 525;
// 525;
// Screen.getPrimary().getBounds().getMaxY();
public static Font Cinzel = (Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 16));
public static VBox console = new VBox(2);
public static TextField input = new TextField();
public static ScrollPane scroll = new ScrollPane();
public static BorderPane root = new BorderPane();
public static String s;
public static Parent Window() {
root.setMinSize(WIDTH, (HEIGHT - input.getHeight()));
root.setStyle("-fx-background-color: #232323;");
scroll.setContent(console);
root.setCenter(scroll);
scroll.setStyle("-fx-background: #232323;"
+ "-fx-background-color: transparent;"
+ "-fx-border-color: #232323;"
+ "-fx-focus-color: #232323;"
);
scroll.setHbarPolicy(ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollBarPolicy.NEVER);
scroll.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, null, null)));
console.setStyle("-fx-background-color: #232323;"
+ "-fx-focus-color: #232323;");
console.heightProperty().addListener(new ChangeListener<Object>() {
#Override
public void changed(ObservableValue<?> observable, Object oldValue, Object newValue) {
scroll.setVvalue((Double)newValue);
}
});
HBox hbox = new HBox();
hbox.setPrefSize(WIDTH, 16);
root.setBottom(hbox);
Text carrot = new Text(" >");
carrot.setFont(Font.loadFont("file:fonts/static/Cinzel-Medium.ttf", 26));
carrot.setFill(Color.WHITE);
input.setStyle("-fx-background-color: transparent;"
+ "-fx-text-fill: #FFFFFF;"
+ "-fx-highlight-fill: #FFFFFF;"
+ "-fx-highlight-text-fill: #232323;"
// + "-fx-border-color: #FFFFFF;"
// + "-fx-border-width: .5;"
);
input.setFont(Cinzel);
input.setMinWidth(console.getWidth());
input.setOnAction(e -> {
String s = (input.getText()).stripTrailing();
input.clear();
});
Pane pane = new Pane();
root.getChildren().add(pane);
hbox.getChildren().addAll(carrot, input);
return root;
}
This isn't the main issue as I've stated, once getting the scaled width for the TextField the process of for setWrappingWidth() for displaying the text should be the if a solution is found, here's how it goes:
#SuppressWarnings("static-access")
public void print(String s, Color c) {
Ce Ce = new Ce();
HBox text1 = new HBox();
text1.setMinWidth(Ce.WIDTH);
text1.setMaxWidth(Ce.WIDTH);
Text tCarrot = new Text(" > ");
tCarrot.setFont(Ce.Cinzel);
tCarrot.setFill(c);
Text text2 = new Text();
final IntegerProperty i = new SimpleIntegerProperty(0);
Timeline tl = new Timeline();
KeyFrame kf = new KeyFrame(
Duration.seconds(textSpeed(fastText)),
e1 -> {
if(i.get() > s.length()) {
tl.stop();
} else {
text2.setText(s.substring(0, i.get()));
i.set(i.get() + 1);
}
});
tl.getKeyFrames().add(kf);
tl.setCycleCount(Animation.INDEFINITE);
tl.play();
text2.setFill(c);
text2.setFont(Ce.Cinzel);
text2.setWrappingWidth(Ce.WIDTH - 40);
text1.getChildren().addAll(tCarrot, text2);
Ce.console.getChildren().add(text1);
Ce.console.setMargin(text1, new Insets(5, 0, 0, 3));
}
Lastly, the HEIGHT of the VBox for the displayed Text works just as intended, it's just the setting/updating the WIDTH to set it to the size of the window whether Windowed of Full screened that is the main issue here.
Try this app. It will not be exactly what you want but may provide some useful help for you if you study it, if not just ignore it, tears can keep you blind, and sometimes, that is ok.
The implementation follows the suggestions you have received in the comments on your questions which together explain what is being done and why, so I won't provide much commentary on the solution here.
Type text in the input bar, press enter and it will appear in the listview for the console log. Use the Toggle full-screen button to toggle full-screen mode on or off.
Console.java
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Console extends VBox {
private final ObservableList<String> consoleLog = FXCollections.observableArrayList();
private final ListView<String> logView = new ListView<>(consoleLog);
public Console(Stage stage) {
VBox.setVgrow(logView, Priority.ALWAYS);
HBox ribbon = createRibbon(
createFullScreenToggle(stage)
);
ribbon.setMinHeight(HBox.USE_PREF_SIZE);
getChildren().addAll(
ribbon,
logView
);
}
private ToggleButton createFullScreenToggle(Stage stage) {
ToggleButton fullScreenToggle = new ToggleButton("Toggle full screen");
fullScreenToggle.setOnAction(e ->
stage.setFullScreen(
fullScreenToggle.isSelected()
)
);
return fullScreenToggle;
}
private HBox createRibbon(ToggleButton fullscreenToggle) {
Text prompt = new Text(">");
TextField input = new TextField();
input.setOnAction(e -> {
consoleLog.add(0, input.getText());
logView.scrollTo(0);
input.clear();
});
HBox.setHgrow(input, Priority.ALWAYS);
HBox ribbon = new HBox(10,
prompt,
input,
fullscreenToggle
);
ribbon.setAlignment(Pos.BASELINE_LEFT);
return ribbon;
}
public ObservableList<String> getConsoleLog() {
return consoleLog;
}
}
ConsoleApplication.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ConsoleApplication extends Application {
#Override
public void start(Stage stage) {
Console console = new Console(stage);
console.getConsoleLog().addAll(
TEXT.lines().toList()
);
stage.setScene(
new Scene(
console
)
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private static final String TEXT = """
W. Shakespeare - Sonnet 148
O me, what eyes hath Love put in my head,
Which have no correspondence with true sight!
Or, if the have, where is my judgement fled,
That censures falsely what they see aright?
If that be fair whereon my false eyes dote,
What means the world to say it is not so?
If it be not, then love doth well denote
Love’s eye is not so true as all men’s ‘No.’
How can it? O, how can Love’s eye be true,
That is so vex’d with watching and with tears?
No marvel then, though I mistake my view;
The sun itself sees not till heaven clears.
O cunning Love! with tears thou keep’st me blind.
Lest eyes well-seeing thy foul faults should find.
""";
}
If you want to increase the nodes height/width according to the viewport, then this's not the best practice, because every user will have the same font size at the end. What you can do is to make the font resizable by either GUI buttons or keyboard/mouse keys.
Here is a modification on your code, that will allow users to use ctrl + mouse wheel to increase/decrease the font (like any browser or terminal):
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ConsoleTest extends Application {
#Override
public void start(Stage stage) {
Scene scene = new Scene(new GameWindow().Console(), 600, 600);
stage.setTitle("Console");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
class GameWindow {
public static Console c = new Console();
public Parent Console() {
for (int i = 0; i < 100; i++) c.addText(new Text("Test" + i));
return c;
}
}
class Console extends BorderPane {
private final SimpleDoubleProperty fontSize = new SimpleDoubleProperty(20);
private final ObjectBinding<Font> fontBinding = Bindings.createObjectBinding(() -> Font.font(fontSize.get()), fontSize);
private final VBox console;
public Console() {
console = new VBox();
console.setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
ScrollPane scroll = new ScrollPane(console);
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
scroll.setFitToHeight(true);
scroll.setFitToWidth(true);
scroll.setPadding(Insets.EMPTY);
Text caret = new Text(" >");
caret.fontProperty().bind(fontBinding);
caret.setFill(Color.WHITE);
TextField input = new TextField();
input.setStyle("-fx-background-color: transparent;" + "-fx-text-fill: #FFFFFF;" + "-fx-highlight-fill: #FFFFFF;" + "-fx-highlight-text-fill: #232323;");
input.fontProperty().bind(fontBinding);
HBox inputBar = new HBox(2, caret, input);
inputBar.setStyle("-fx-background-color: #232323;");
inputBar.setAlignment(Pos.CENTER_LEFT);
setCenter(scroll);
setBottom(inputBar);
EventHandler<ScrollEvent> scrollEvent = e -> {
if (e.isControlDown()) {
if (e.getDeltaY() > 0) {
fontSize.set(fontSize.doubleValue() + 2);
} else {
double old;
fontSize.set((old = fontSize.doubleValue()) < 10 ? old : old - 2);
}
e.consume();
}
};
inputBar.setOnScroll(scrollEvent);
console.setOnScroll(scrollEvent);
}
public void addText(Text text) {
text.fontProperty().bind(fontBinding);
text.setFill(Color.WHITE);
console.getChildren().add(text);
}
}

How can you layout a JavaFX Node that is padded with a proportion of the available space?

It is fairly easy to use the standard layout Panes in JavaFX to get fixed padding around a content node.
However are there settings for any of the standard layout Panes that would put the content in the middle ¾ of the pane's width with padding of 1/8 of the width on each side?
You can, as suggested by James_D, use a GridPane with the appropriate constraints to accomplish this. Here's an example:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.RowConstraints;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage primaryStage) {
Region region = new Region();
region.setStyle("-fx-background-color: firebrick;");
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.add(region, 0, 0);
ColumnConstraints cc = new ColumnConstraints(0, Region.USE_COMPUTED_SIZE, Double.MAX_VALUE);
cc.setPercentWidth(75);
cc.setHgrow(Priority.ALWAYS);
cc.setHalignment(HPos.CENTER);
grid.getColumnConstraints().add(cc);
RowConstraints rr = new RowConstraints(0, Region.USE_COMPUTED_SIZE, Double.MAX_VALUE);
rr.setPercentHeight(100);
rr.setVgrow(Priority.ALWAYS);
rr.setValignment(VPos.CENTER);
grid.getRowConstraints().add(rr);
primaryStage.setScene(new Scene(grid, 500, 300));
primaryStage.show();
}
}
Another option is to create your own layout which, assuming I didn't make a mistake, is not too difficult:
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
public class CustomPane extends Pane {
// value should be between 0.0 (0%) and 1.0 (100%)
private final DoubleProperty widthRatio =
new SimpleDoubleProperty(this, "widthRatio", 0.75) {
#Override
protected void invalidated() {
requestLayout();
}
};
public final void setWidthRatio(double widthRatio) { this.widthRatio.set(widthRatio); }
public final double getWidthRatio() { return widthRatio.get(); }
public final DoubleProperty widthRatioProperty() { return widthRatio; }
public CustomPane() {}
public CustomPane(double widthRatio) {
setWidthRatio(widthRatio);
}
#Override
protected void layoutChildren() {
double ratio = getWidthRatioClamped();
double x = snappedLeftInset();
double y = snappedTopInset();
double w = getWidth() - snappedRightInset() - x;
double h = getHeight() - snappedBottomInset() - y;
// could do the same thing with the height if you want
x = snapPositionX(x + ((w - w * ratio) / 2.0));
w = snapSizeX(w * ratio);
for (Node child : getManagedChildren()) {
layoutInArea(child, x, y, w, h, -1.0, HPos.CENTER, VPos.CENTER);
}
}
private double getWidthRatioClamped() {
return Math.max(0.0, Math.min(1.0, getWidthRatio()));
}
}
Note that both solutions will take the child nodes' min/pref/max widths and heights into account. If the child node is not resizable (e.g. ImageView, MediaView, etc.) then it won't work as expected. Though you can of course create workarounds for non-resizable nodes. For instance, here's another answer of mine which creates a "resizable ImageView".
Also, note that both solutions layout the children in the area available after the space taken up from any padding and borders is subtracted.

JavaFX css border-radius issue

I am trying to simulate the effect one would get from this css example:
border-radius: 50%;
From searching the API and reading posts on forums including this one, I found that I should be using -fx-background-radius. This however is not giving me the wanted effect.
I setup a picture as the background using -fx-background-image:url(...) and then I want to make it into a circle.
How can I achieve this?
Update
So I see that I was not being too specific so let me try to elaborate:
I created a Pane object, that does extend the Region class from JavaFX.
main.fxml:
...
<Pane styleClass="wrapper">
<Pane layoutX="34.0" layoutY="28.0" styleClass="image" />
</Pane>
For this pane I created the styleclass image as seen above.
main.css:
.list-contact .image {
-fx-alignment:left;
-fx-pref-height:40px;
-fx-pref-width:40px;
-fx-background-radius:50%;
-fx-background-image:url(...);
-fx-background-repeat:no-repeat;
}
The effect I get:
The effect I want:
I hope this explains it better.
This is not possible from CSS alone, since ImageView does not support any of Region's CSS properties.
However you can use a Ellipse as clip for the ImageView:
#Override
public void start(Stage primaryStage) throws MalformedURLException {
Image img = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Space_Needle_2011-07-04.jpg/304px-Space_Needle_2011-07-04.jpg");
ImageView iv = new ImageView(img);
Ellipse ellipse = new Ellipse(img.getWidth() / 2, img.getHeight() / 2, img.getWidth() / 2, img.getHeight() / 2);
iv.setClip(ellipse);
Text text = new Text("Space Needle, Seattle, Washington, USA");
StackPane.setAlignment(text, Pos.TOP_CENTER);
StackPane root = new StackPane(text, iv);
Scene scene = new Scene(root, img.getWidth(), img.getHeight());
scene.setFill(Color.AQUAMARINE);
primaryStage.setScene(scene);
primaryStage.show();
}
I know it doesn't look good to let the image cover the text. This is only done for the purpose of demonstration.
It looks like a CSS border-radius: 50% should create an elliptical border, and JavaFX CSS does support the % shorthand for either -fx-border-radius or -fx-background-radius. To get the desired effect, however, use Path.subtract() to create an elliptical matte for the image, as shown below.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
/**
* #see http://stackoverflow.com/a/38008678/230513
*/
public class Test extends Application {
private final Image IMAGE = new Image("http://i.imgur.com/kxXhIH1.jpg");
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Test");
int w = (int) (IMAGE.getWidth());
int h = (int) (IMAGE.getHeight());
ImageView view = new ImageView(IMAGE);
Rectangle r = new Rectangle(w, h);
Ellipse e = new Ellipse(w / 2, h / 2, w / 2, h / 2);
Shape matte = Path.subtract(r, e);
matte.setFill(Color.SIENNA);
StackPane root = new StackPane();
root.getChildren().addAll(view, matte);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
In one Line with Circle as Clip.You can use setClip(any shape).:
imageView.setClip(new Circle(width,height,radius);
The width,height,radius have to be slighty smaller that ImageView size to work.
Inspired by GuiGarage web site.

Tooltip isn't being displayed on ScrollPane

Following the tutorial here I tried to create a Tooltip on a ScrollPane using the following code:
final ScrollPane scroll = new ScrollPane();
scroll.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
pointer = MouseInfo.getPointerInfo();
point = pointer.getLocation();
color = robot.getPixelColor((int) point.getX(), (int) point.getY());
Tooltip tooltip = new Tooltip();
tooltip.setText(" " + color);
tooltip.activatedProperty();
scroll.setTooltip(tooltip);
System.out.println("Color at: " + point.getX() + "," + point.getY() + " is: " + color);
}
});
The tooltip however refuses to show itself on the ScrollPane but the output of "Color at: ..." is being printed so I am sure that handle is being called.
EDIT : On the suggestion of jewelsea , I tried putting the eventHandler on the content ,rather than the pane, but to no effect.
If I understand what you're trying to do, you really only need to install the tooltip once, and then just modify its text as the mouse moves.
This works for me:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ImageTooltipTest extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Image image = new Image("http://www.publicdomainpictures.net/pictures/30000/velka/tropical-paradise.jpg");
final ImageView imageView = new ImageView();
imageView.setImage(image);
final ScrollPane scroller = new ScrollPane();
scroller.setContent(imageView);
final Tooltip tooltip = new Tooltip();
scroller.setTooltip(tooltip);
scroller.getContent().addEventHandler(MouseEvent.MOUSE_MOVED, event -> {
Image snapshot = scroller.getContent().snapshot(null, null);
int x = (int) event.getX();
int y = (int) event.getY();
PixelReader pixelReader = snapshot.getPixelReader();
Color color = pixelReader.getColor(x, y);
String text = String.format("Red: %.2f%nGreen: %.2f%nBlue: %.2f",
color.getRed(),
color.getGreen(),
color.getBlue());
tooltip.setText(text);
});
root.setCenter(scroller);
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Transparent Stage should not minimized when clicked inside in Javafx

I am learning to create Screen Recording application in JavaFx. I want user to resize the rectangle to decide the screen capture area. I have made stage and scene Transparent by primaryStage.initStyle(StageStyle.TRANSPARENT); and scene.setFill(null); .
I am able to resize the rectangular section but the problem is When I click inside the stage, It gets minimized as it is transparent. How to solve this issue ?
I have seen this application screencast-o-matics and following the same. Please guide me on this.
Edit::
Code:
import java.awt.Toolkit;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ScreenCaptureDemo extends Application {
Rectangle rectangle ;
double x0,y0;
public static void main(String[] args) {
launch(ScreenCaptureDemo.class);
}
#Override
public void start(final Stage primaryStage) throws Exception {
BorderPane borderPane = new BorderPane();
GridPane gridPane = new GridPane();
HBox box = new HBox();
Button button1 = new Button("button2");
Button button2 = new Button("Button3");
Button button = new Button("button");
box.getChildren().add(button);
box.getChildren().add(button1);
box.getChildren().add(button2);
rectangle = new Rectangle(500.0, 500.0);
rectangle.setStrokeWidth(2);
rectangle.setArcHeight(15.0);
rectangle.setArcWidth(15.0);
rectangle.setFill(Color.TRANSPARENT);
rectangle.setStroke(Color.RED);
rectangle.setStrokeWidth(5);
rectangle.getStrokeDashArray().addAll(3.0,13.0,3.0,7.0);
gridPane.add(rectangle, 0, 0);
gridPane.add(box, 0, 1);
borderPane.setCenter(gridPane);
Scene scene = new Scene(borderPane,Toolkit.getDefaultToolkit().getScreenSize().getWidth()-100,Toolkit.getDefaultToolkit().getScreenSize().getHeight()-100);
scene.setOnMouseDragged(mouseHandler);
scene.setOnMousePressed(mouseHandler);
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.TRANSPARENT);
scene.setFill(null);
rectangle.setMouseTransparent(true);
rectangle.setPickOnBounds(true);
primaryStage.show();
}
void setScaleRect(double sX, double sY){
rectangle.setHeight(sY);
rectangle.setWidth(sX);
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
double heightLowerLimit = rectangle.getHeight()-500;
double heightUpperLimit = rectangle.getHeight()+500;
double widthLowerLimit = rectangle.getWidth()-500;
double widthUpperLimit = rectangle.getWidth()+500;
if ((mouseEvent.getY() >heightLowerLimit && mouseEvent.getY() < heightUpperLimit) &&
(mouseEvent.getX() >widthLowerLimit && mouseEvent.getX() < widthUpperLimit)
) {
double scaleX = mouseEvent.getX();
double scaleY = mouseEvent.getY();
setScaleRect(scaleX, scaleY);
} else if ((mouseEvent.getY() >heightLowerLimit && mouseEvent.getY() < heightUpperLimit)
&& (mouseEvent.getX() <widthLowerLimit && mouseEvent.getX() > widthUpperLimit)) {
double scaleY = mouseEvent.getY();
double scaleX=rectangle.getWidth();
setScaleRect(scaleX, scaleY);
} else if (mouseEvent.getY() != rectangle.getHeight()
&& mouseEvent.getX() == rectangle.getWidth()) {
double scaleX = mouseEvent.getX();
double scaleY=rectangle.getHeight();
setScaleRect(scaleX, scaleY);
}
}
}
};
}
Thank you in advance
Fill the rectangle as
rectangle.setFill(Color.web("blue", 0.1));
// or more transparent
rectangle.setFill(Color.web("gray", 0.01));

Resources