I have JavaFX project and I need coordinates of each dot in the orange line from image bellow.
https://i.stack.imgur.com/A7zVa.png
I spent a lot of hours googling but I can not find a solution.
It is a simple application. I need those coordinates beacuse I need to make G CODE for CNC machine.
My Code is:
public class KS2 extends Application {
private LineChart<Number, Number> chart;
#Override
public void start(Stage primaryStage) throws Exception {
final NumberAxis xAxis = new NumberAxis(0.0, 150.0, 2);
final NumberAxis yAxis = new NumberAxis(0.0, 100.0, 2);
// Flip the axis
// yAxis.setScaleY(-1);
Rectangle r = new Rectangle(0, 0, 80, 50);
r.setFill(Color.TRANSPARENT);
r.setStrokeWidth(0.5);
r.setStroke(Color.BLACK);
this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
#Override
public void layoutPlotChildren() {
super.layoutPlotChildren();
r.getTransforms().setAll(chartDisplayTransform(xAxis, yAxis));
// note nodes don't get removed from the plot children, and this method may be
// called often:
if (!getPlotChildren().contains(r)) {
getPlotChildren().add(r);
}
}
};
this.chart.setAnimated(false);
XYChart.Series series = new XYChart.Series();
series.getData().add(new XYChart.Data(54, 50));
series.getData().add(new XYChart.Data(80, 0));
//series.setName("My portfolio");
this.chart.getData().add(series);
VBox vbox = new VBox(this.chart);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(400);
primaryStage.show();
}
private Transform chartDisplayTransform(NumberAxis xAxis, NumberAxis yAxis) {
return new Affine(xAxis.getScale(), 0, xAxis.getDisplayPosition(0), 0, yAxis.getScale(),
yAxis.getDisplayPosition(0));
}
public static void main(String[] args) {
Application.launch(args);
}
}
Related
The JavaFX coordinate system draws Y coords from the top of screen, and is positive downwards. I would like it to be positive upwards, and start from the bottom of screen.
There needs to be a translate, and the text nodes need to be flipped.
And with that, hopefully the drawn rectangle will be positioned the "natural" way we do it in math class. With its bottom-left at the origin, expanding to the top-right.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class FlippedExampleChart extends Application {
private LineChart<Number, Number> chart;
#Override
public void start(Stage primaryStage) throws Exception {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
// Flip the axis
yAxis.setScaleY(-1);
// TODO How to translate to bottom of screen.
// TODO How to flip the text nodes.
this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
#Override
public void layoutPlotChildren() {
super.layoutPlotChildren();
double height = yAxis.getDisplayPosition(100);
Rectangle r = new Rectangle(0, 0, 50, height);
r.setFill(Color.GREEN);
getPlotChildren().addAll(r);
}
};
this.chart.setAnimated(false);
VBox vbox = new VBox(this.chart);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(400);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
I'm assuming here the aim is to draw a shape using the coordinate system defined by the chart axes.
The easiest way is probably to transform the shape instead of the axis. You can create a utility method for this:
private Transform chartDisplayTransform(NumberAxis xAxis, NumberAxis yAxis) {
return new Affine(
xAxis.getScale(), 0, xAxis.getDisplayPosition(0),
0, yAxis.getScale(), yAxis.getDisplayPosition(0)
);
}
One other note about your code: the layoutPlotChildren() method doesn't necessarily remove nodes, so you may end up adding more rectangles than you expect with the code you posted.
Here's a version of your code that uses this method (and ensures the rectangle is only added once).
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Affine;
import javafx.scene.transform.Transform;
import javafx.stage.Stage;
public class FlippedExampleChart extends Application {
private LineChart<Number, Number> chart;
#Override
public void start(Stage primaryStage) throws Exception {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
// Flip the axis
// yAxis.setScaleY(-1);
Rectangle r = new Rectangle(0, 0, 50, 100);
r.setFill(Color.GREEN);
this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
#Override
public void layoutPlotChildren() {
super.layoutPlotChildren();
r.getTransforms().setAll(chartDisplayTransform(xAxis, yAxis));
// note nodes don't get removed from the plot children, and this method may be
// called often:
if (!getPlotChildren().contains(r)) {
getPlotChildren().add(r);
}
}
};
this.chart.setAnimated(false);
VBox vbox = new VBox(this.chart);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(400);
primaryStage.show();
}
private Transform chartDisplayTransform(NumberAxis xAxis, NumberAxis yAxis) {
return new Affine(xAxis.getScale(), 0, xAxis.getDisplayPosition(0), 0, yAxis.getScale(),
yAxis.getDisplayPosition(0));
}
public static void main(String[] args) {
Application.launch(args);
}
}
And the result:
If you have multiple nodes to treat this way, the strategy is to add them to a Group, and apply the transform to the Group:
#Override
public void start(Stage primaryStage) throws Exception {
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
Group extraNodes = new Group();
this.chart = new LineChart<Number, Number>(xAxis, yAxis) {
#Override
public void layoutPlotChildren() {
super.layoutPlotChildren();
Rectangle r1 = new Rectangle(0, 0, 50, 100);
r1.setFill(Color.GREEN);
Rectangle r2 = new Rectangle(70, 0, 30, 20);
r2.setFill(Color.AQUAMARINE);
extraNodes.getChildren().setAll(r1, r2);
extraNodes.getTransforms().setAll(chartDisplayTransform(xAxis, yAxis));
// note nodes don't get removed from the plot children, and this method may be
// called often:
if (!getPlotChildren().contains(extraNodes)) {
getPlotChildren().add(extraNodes);
}
}
};
this.chart.setAnimated(false);
VBox vbox = new VBox(this.chart);
Scene scene = new Scene(vbox, 400, 200);
primaryStage.setScene(scene);
primaryStage.setHeight(600);
primaryStage.setWidth(400);
primaryStage.show();
}
Also see this related question
For my project I have to realize a zoomable lineChart. I found many code of zoom but none of them is working. In fact, I think that the problem is the fact that my windows is divided in many windows, and in 4 of these windows, there are the charts. Thus, the zoom looks like it works but when I use the zoom, the new axis is not what it's supposed to be :
1) I'm choosing where i want to zoom :
https://imgur.com/a/j6LwrsH
2) chart is "reloading" with new axis :
https://imgur.com/a/SyeqnEV
public class ZoomableLineChart<X extends Number, Y extends Number> extends LineChart<X, Y> {
private final Region userTrackArea = new Region();
XYChart.Series series;
double valueX;
double valueY;
BorderPane chartContainer;
public ZoomableLineChart( Axis xAxis, Axis yAxis, XYChart.Series series, BorderPane border, double valueX, double valueY ) {
super(xAxis, yAxis);
this.chartContainer = border;
this.valueX = valueX;
this.valueX = valueX;
final LineChart<Number, Number> chart = createChart();
chart.getData().add(series);
final StackPane StackChartContainer = new StackPane();
StackChartContainer.getChildren().add(chart);
StackChartContainer.setOnMouseClicked(this::handleMouseTrackingClicked);
final Rectangle zoomRect = new Rectangle();
zoomRect.setManaged(false);
zoomRect.setFill(Color.LIGHTSEAGREEN.deriveColor(0, 1, 1, 0.5));
StackChartContainer.getChildren().add(zoomRect);
setUpZooming(zoomRect, chart);
final HBox controls = new HBox();
controls.setSpacing(10);
controls.setPadding(new Insets(10));
controls.setAlignment(Pos.CENTER);
final Button zoomButton = new Button("Zoom");
final Button resetButton = new Button("Reset");
zoomButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
doZoom(zoomRect, chart);
}
});
resetButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final NumberAxis xAxis = (NumberAxis)chart.getXAxis();
xAxis.setLowerBound(0);
xAxis.setUpperBound(100);
final NumberAxis yAxis = (NumberAxis)chart.getYAxis();
yAxis.setLowerBound(0);
yAxis.setUpperBound(100);
zoomRect.setWidth(0);
zoomRect.setHeight(0);
}
});
final BooleanBinding disableControls =
zoomRect.widthProperty().lessThan(5)
.or(zoomRect.heightProperty().lessThan(5));
zoomButton.disableProperty().bind(disableControls);
controls.getChildren().add(zoomButton);
controls.getChildren().add(resetButton);
border.setCenter(StackChartContainer);
border.setBottom(controls);
}
private void handleMouseTrackingClicked(final MouseEvent mouseEvent) {
final NumberAxis xAxis = (NumberAxis) getXAxis();
final NumberAxis yAxis = (NumberAxis) getYAxis();
final double mouseX = mouseEvent.getX();
final double mouseY = mouseEvent.getY();
valueX = xAxis.getValueForDisplay(mouseX).doubleValue();
valueY = yAxis.getValueForDisplay(mouseY).doubleValue();
// System.out.printf("Mouse %f %f -> value %f (%f %f) %f (%f %f)", mouseX, mouseY,
// valueX, xAxis.getLowerBound(), xAxis.getUpperBound(),
// valueY, yAxis.getLowerBound(), yAxis.getUpperBound()).println();
System.out.println(valueX + "," + valueY);
}
public static BorderPane creerGrapheZoomable(XYChart.Series series, BorderPane chartContainer) {
final LineChart<Number, Number> chart = createChart();
chart.getData().add(series);
final StackPane StackChartContainer = new StackPane();
StackChartContainer.getChildren().add(chart);
final Rectangle zoomRect = new Rectangle();
zoomRect.setManaged(false);
zoomRect.setFill(Color.LIGHTSEAGREEN.deriveColor(0, 1, 1, 0.5));
StackChartContainer.getChildren().add(zoomRect);
setUpZooming(zoomRect, chart);
final HBox controls = new HBox();
controls.setSpacing(10);
controls.setPadding(new Insets(10));
controls.setAlignment(Pos.CENTER);
final Button zoomButton = new Button("Zoom");
final Button resetButton = new Button("Reset");
zoomButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
doZoom(zoomRect, chart);
}
});
resetButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final NumberAxis xAxis = (NumberAxis)chart.getXAxis();
xAxis.setLowerBound(0);
xAxis.setUpperBound(100);
final NumberAxis yAxis = (NumberAxis)chart.getYAxis();
yAxis.setLowerBound(0);
yAxis.setUpperBound(100);
zoomRect.setWidth(0);
zoomRect.setHeight(0);
}
});
final BooleanBinding disableControls =
zoomRect.widthProperty().lessThan(5)
.or(zoomRect.heightProperty().lessThan(5));
zoomButton.disableProperty().bind(disableControls);
controls.getChildren().add(zoomButton);
controls.getChildren().add(resetButton);
chartContainer.setCenter(StackChartContainer);
chartContainer.setBottom(controls);
return chartContainer;
}
private static LineChart<Number, Number> createChart() {
final NumberAxis xAxis = createAxis();
final NumberAxis yAxis = createAxis();
final LineChart<Number, Number> chart = new LineChart<>(xAxis, yAxis);
chart.setAnimated(false);
chart.setCreateSymbols(false);
return chart ;
}
private static NumberAxis createAxis() {
final NumberAxis xAxis = new NumberAxis();
xAxis.setAutoRanging(false);
xAxis.setLowerBound(0);
xAxis.setUpperBound(100);
return xAxis;
}
private static void setUpZooming(final Rectangle rect, final Node zoomingNode) {
final ObjectProperty<Point2D> mouseAnchor = new SimpleObjectProperty<>();
zoomingNode.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("Mouse Event OK");
mouseAnchor.set(new Point2D(event.getX(), event.getY()));
System.out.println(event.getX() + " " + event.getY() );
rect.setWidth(0);
rect.setHeight(0);
}
});
zoomingNode.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
double x = event.getX();
double y = event.getY();
rect.setX(Math.min(x, mouseAnchor.get().getX()));
rect.setY(Math.min(y, mouseAnchor.get().getY()));
System.out.println(x + ' ' + y);
rect.setWidth(Math.abs(x - mouseAnchor.get().getX()));
rect.setHeight(Math.abs(y - mouseAnchor.get().getY()));
}
});
}
private static void doZoom(Rectangle zoomRect, LineChart<Number, Number> chart) {
Point2D zoomTopLeft = new Point2D(zoomRect.getX(), zoomRect.getY());
Point2D zoomBottomRight = new Point2D(zoomRect.getX() + zoomRect.getWidth(), zoomRect.getY() + zoomRect.getHeight());
final NumberAxis yAxis = (NumberAxis) chart.getYAxis();
Point2D yAxisInScene = yAxis.localToScene(0, 0);
final NumberAxis xAxis = (NumberAxis) chart.getXAxis();
Point2D xAxisInScene = xAxis.localToScene(0, 0);
double xOffset = zoomTopLeft.getX() - yAxisInScene.getX() ;
double yOffset = zoomBottomRight.getY() - xAxisInScene.getY();
double xAxisScale = xAxis.getScale();
double yAxisScale = yAxis.getScale();
xAxis.setLowerBound(xAxis.getLowerBound() + xOffset / xAxisScale);
xAxis.setUpperBound(xAxis.getLowerBound() + zoomRect.getWidth() / xAxisScale);
yAxis.setLowerBound(yAxis.getLowerBound() + yOffset / yAxisScale);
yAxis.setUpperBound(yAxis.getLowerBound() - zoomRect.getHeight() / yAxisScale);
System.out.println(yAxis.getLowerBound() + " , " + yAxis.getUpperBound());
zoomRect.setWidth(0);
zoomRect.setHeight(0);
}
public int getValueX() {
return (int) valueX;
}
public int getValueY() {
return (int) valueY;
}
}
i have following code:
final TreeMap<Integer, Double> ADLMap = new TreeMap<>();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
final String currency = "currreny";
ADL(currency);
stage.setTitle("Line Chart Sample");
//defining the axes
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Number of Month");
//creating the chart
final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);
lineChart.setTitle("Stock Monitoring, 2010");
//defining a series
XYChart.Series ADLChart = new XYChart.Series();
XYChart.Series regularChart = new XYChart.Series();
ADLChart.setName("My portfolio");
chartMap.entrySet().forEach(entry -> regularChart.getData().add(new XYChart.Data(entry.getKey(), entry.getValue())));
//populating the series with data
ADLMap.entrySet().forEach(entry -> ADLChart.getData().add(new XYChart.Data(entry.getKey(), entry.getValue())));
System.out.println(ADLMap);
lineChart.setCreateSymbols(false);
Scene scene = new Scene(lineChart, 1200, 1000);
//lineChart.getData().add(regularChart);
lineChart.getData().add(ADLChart);
stage.setScene(scene);
stage.show();
final double SCALE_DELTA = 1.1;
lineChart.setOnScroll(new EventHandler<ScrollEvent>() {
public void handle(ScrollEvent event) {
event.consume();
if (event.getDeltaY() == 0) {
return;
}
double scaleFactor = (event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
lineChart.setScaleX(lineChart.getScaleX() * scaleFactor);
lineChart.setScaleY(lineChart.getScaleY() * scaleFactor);
}
});
lineChart.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
if (event.getClickCount() == 2) {
lineChart.setScaleX(1.0);
lineChart.setScaleY(1.0);
}
}
});
}
private void ADL(final String currency) {
double counter = -4000000.0;
int mapCounter = 0;
while (counter < 4000000) {
ADLMap.put(mapCounter++, counter++);
}
}
the Map contains following values:
keys n+1 n€IN
Values from range from -10.000.000 to + 10.000.000
My Problem: It doesn't plot values at all. At least i cannot see any.
Can someone please help?
My mistake was that a complex algorithm produced an inifnity nuber which was placed in the TreeMap. The Graph couldn't plot it ofc.
Is it possible to move/shift the tick labels into the chart. Currently I see api's to hide/show tick labels is there an API that moves the tick labels inside the chart? If there isn't an API then is there a technique that I can use/apply to get this done?
Current code
public class Graph extends Application{
private NumberAxis xAxis;
private NumberAxis yAxis;
public static void main(final String[] args)
{
launch(args);
}
#Override
public void start(final Stage primaryStage) throws Exception
{
xAxis = new NumberAxis(0, 300, 20);
xAxis.setAutoRanging(false);
xAxis.setAnimated(false);
xAxis.setMinorTickVisible(false);
xAxis.setTickLabelsVisible(false);
xAxis.setTickMarkVisible(false);
yAxis = new NumberAxis(30, 240, 30);
yAxis.setAutoRanging(false);
yAxis.setAnimated(false);
yAxis.setTickMarkVisible(false);
yAxis.setMinorTickVisible(false);
yAxis.setMinorTickCount(3);
final LineChart<Number, Number> ctg = new LineChart<>(xAxis, yAxis);
ctg.setAnimated(false);
ctg.setCreateSymbols(false);
ctg.setAlternativeRowFillVisible(false);
ctg.setLegendVisible(false);
ctg.setHorizontalGridLinesVisible(true);
ctg.setVerticalGridLinesVisible(true);
Series<Number, Number> series = new LineChart.Series<>();
ctg.getData().add(series);
for (int i = 0; i < 300; i += 5) {
XYChart.Series minorYGrid = new XYChart.Series();
minorYGrid.getData().add(new XYChart.Data(i, 30));
minorYGrid.getData().add(new XYChart.Data(i, 240));
ctg.getData().add(minorYGrid);
}
for (int i = 40; i <= 240; i += 10) {
XYChart.Series minorXGrid = new XYChart.Series();
minorXGrid.getData().add(new XYChart.Data(0, i));
minorXGrid.getData().add(new XYChart.Data(500, i));
ctg.getData().add(minorXGrid);
}
final Scene scene = new Scene(ctg, 1600, 400);
scene.getStylesheets().add("resources/application.css");
primaryStage.setScene(scene);
primaryStage.show();
}
}
Current result
Expected result
Translating a Single Axis
You can translate the y axis on the chart.
For example:
yAxis.translateXProperty().bind(
xAxis.widthProperty().divide(2)
);
To ensure the axis is displayed on top of the chart, you could set the depth buffer to true on the scene and set the z co-ordinate of the yAxis to -1.
yAxis.setTranslateZ(-1);
Translating Multiple Axes
Your "Expected result" actually has multiple vertical axes. Unfortunately there is no clone method to clone a node in JavaFX. So you will have to create a new axis and layer it on top of the chart. One way to accomplish that (which is a bit overkill and inefficient), is to create a completely new chart and layer it on top of the old one, similar to what is done in the solution to draw layers of XYCharts. The other way to do it, which is probably preferable but a bit trickier, would be just create another axis and stack it over the original chart.
Sample Code
MultiAxisChart.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MultiAxisChart extends Application {
#Override
public void start(final Stage primaryStage) throws Exception {
final StackPane chartStack = createChartStack();
final Scene scene = new Scene(chartStack, 1600, 400, true);
primaryStage.setScene(scene);
primaryStage.show();
}
private StackPane createChartStack() {
LineChart<Number, Number> bottomChart = createChart();
LineChart<Number, Number> topChart = createChart();
bottomChart.getYAxis().translateXProperty().bind(
bottomChart.getXAxis().widthProperty().multiply(1.0/3)
);
topChart.getYAxis().translateXProperty().bind(
topChart.getXAxis().widthProperty().multiply(2.0/3)
);
bottomChart.getYAxis().setTranslateZ(-1);
topChart.getYAxis().setTranslateZ(-1);
topChart.getStylesheets().addAll(getClass().getResource(
"overlay-chart.css"
).toExternalForm());
return new StackPane(bottomChart, topChart);
}
private LineChart<Number, Number> createChart() {
NumberAxis xAxis = new NumberAxis(0, 300, 20);
xAxis.setAutoRanging(false);
xAxis.setAnimated(false);
xAxis.setMinorTickVisible(false);
xAxis.setTickLabelsVisible(false);
xAxis.setTickMarkVisible(false);
NumberAxis yAxis = new NumberAxis(30, 240, 30);
yAxis.setAutoRanging(false);
yAxis.setAnimated(false);
yAxis.setTickMarkVisible(false);
yAxis.setMinorTickVisible(false);
yAxis.setMinorTickCount(3);
final LineChart<Number, Number> ctg = new LineChart<>(xAxis, yAxis);
ctg.setAnimated(false);
ctg.setCreateSymbols(false);
ctg.setAlternativeRowFillVisible(false);
ctg.setLegendVisible(false);
ctg.setHorizontalGridLinesVisible(true);
ctg.setVerticalGridLinesVisible(true);
return ctg;
}
public static void main(final String[] args) {
launch(args);
}
}
overlay-chart.css
/** file: overlay-chart.css (place in same directory as MultiAxisChart) */
.chart-plot-background {
-fx-background-color: transparent;
}
I am trying to create a custom stage in javafx 2.0. I want that my stage drops shadow on the screen as dropped by other windows... I tried with following code :
public class ChatWindow {
final private Stage stage = new Stage(StageStyle.UNDECORATED);
private Scene scene;
private Group rg;
private Text t = new Text();
private double initx = 0, inity = 0;
public ChatWindow() {
rg = new Group();
scene = new Scene(rg, 320, 240);
//scene.setFill(null);
scene.setFill(new Color(0, 0, 0, 0));
stage.setScene(scene);
stage.show();
setupStage();
}
private void setupStage() {
Rectangle r = new Rectangle(5, 5, stage.getWidth() - 10, stage.getHeight() - 10);
r.setFill(Color.STEELBLUE);
r.setEffect(new DropShadow());
rg.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
initx = me.getScreenX() - stage.getX();// - me.getSceneX();
inity = me.getScreenY() - stage.getY();
}
});
rg.setOnMouseDragged(new EventHandler<MouseEvent>() {
public void handle(MouseEvent me) {
stage.setX(me.getScreenX() - initx);
stage.setY(me.getScreenY() - inity);
}
});
rg.getChildren().add(r);
rg.getChildren().add(t);
}
public void setVisible() {
stage.show();
}
}
I can see the shadow fall, but actually their is a white background on which its falling.
So, its useless, as on colored screen the defect will be visible, will make it look ugly..
This is the screen shot on white screen :
And this on colored screen:
HOw to resolve this issue?? Please help.
You should set style StageStyle.TRANSPARENT, see next code:
public class ChatWindow extends Application {
#Override
public void start(final Stage stage) throws Exception {
stage.initStyle(StageStyle.TRANSPARENT); // here it is
Group rg = new Group();
Scene scene = new Scene(rg, 320, 240, Color.TRANSPARENT);
stage.setScene(scene);
stage.show();
Rectangle r = new Rectangle(5, 5, stage.getWidth() - 10, stage.getHeight() - 10);
r.setFill(Color.STEELBLUE);
r.setEffect(new DropShadow());
rg.getChildren().add(r);
}
public static void main(String[] args) {
launch();
}
}