How to put multiple TextField in a circle in JavaFx - javafx

I am trying to put multiple textfields in a circle in JavaFX. I could add a field in the centre using StackPane as explained in the below-mentioned post but unable to add multiple textfields. I tried using different panes for that but it didn't work.
Added the code that doesn't work.I want to add two text fields at any place inside a circle. Using gridpane for it didn't work. Moreover, I want to create x number of circle dynamically at any place in a gridpane and add multiple text fields to the circle, is it possible to do that using JavaFX?
Hope I am able to explain the problem statement correctly. Any response is appreciated :)
#Override
public void start(Stage arg0) throws Exception {
arg0.setTitle("Text Boxes In circle");
arg0.setMaxWidth(500);
Circle circle = createCircle(); // This function is to form a circle.
Text text = new Text("42");
Text text1 = new Text("36");
text.setBoundsType(TextBoundsType.VISUAL);
text1.setBoundsType(TextBoundsType.VISUAL);
GridPane box = new GridPane();
// box.setConstraints(text, 2, 0); commented this out to check if it was not
// causing problem but still didn't work
// box.setConstraints(text1, 2, 1);
// box.setAlignment(Pos.CENTER); Even used this to center the gridPane didn't
// work either.
StackPane stack = new StackPane();
box.getChildren().addAll(text, text1);
stack.getChildren().addAll(box, circle);
Scene scene = new Scene(stack);
arg0.setScene(scene);
arg0.show();
}
public static void main(String[] args) {
launch(args);
}
private static Circle createCircle() {
final Circle circle = new Circle(100);
circle.setStroke(Color.FORESTGREEN);
circle.setStrokeWidth(10);
circle.setStrokeType(StrokeType.INSIDE);
circle.setFill(Color.AZURE);
return circle;
}
how to put a text into a circle object to display it from circle's center?

Related

Bi-coloring JavaFX TableCell Background?

I have a javafx.scene.control.TableView containing some javafx.scene.control.TableColumns containing some javafx.scene.control.TextFields. Some of the TextFields should get a bi-coloured background: diagonally divided, the upper left half one colour, the lower right half another colour. Like the cells for Ge, Sb, Po in https://de.wikipedia.org/wiki/Periodensystem#/media/Datei:Periodensystem_deutsch_-_neue_Farben.svg. Is this possible without a background image?
Edit: added some code. For simplicity’s sake, i omitted the surrounding table and use now a javafx.scene.text.Text instead of a javafx.scene.control.TextField. The basic setup that follows gives a uniform background to the StackPane which is a start.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
StackPane root = new StackPane();
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Later on, when i will use a 13x13 grid of Text, i will have to imbed each Text into it’s own StackPane or another (perhaps more appropriate) subclass of Region to be able to provide an individually coloured background for each Text. And some of those Texts (especially the one in this example) should have a bi-colour background, both colours divided by the line from left bottom to right upper corner.
The simple solution would be to provide a background image. It’s not too difficult to produce one. But then, i have to produce a new background image for every pair of colours. I would prefer a more flexible solution.
All property setters and CSS properties i have found provide a one-colour-background. But sometimes i require bi-colour.
The proposed LineGradient would be acceptable if everything else fails. I would prefer a clear border between both colours, not a gradient.
Ok, i found a solution, at least for the simplified problem. Thanks to #kleopatra. As a path, i used a javafx.scene.shape.Polygon and filled it with the appropriate colour. Using aStackPane`, it is important to watch the z coordinate. Background naturally bottom, filled polyline as first content in the pane, and text on top.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
Polygon triangle = new Polygon();
triangle.getPoints().addAll(new Double[] { 0.0, 0.0, 200.0, 0.0, 0.0, 200.0 });
triangle.setFill(Color.YELLOW);
StackPane root = new StackPane();
root.getChildren().add(triangle);
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How to add child node without affecting layout of GridPane parent

I want create a app using javafx. It looks like this:
I want to add the zoom function for the chart. When I click the button "Zoom in", the app will become fig2. However, I have no idea to achieve it. When I change the size of pane included the chart, it will change grid pane size, looks like this:
You do not want the zoom to be considered for the gridpane layout. In this can be achieved by applying transforms to the child of the gridpane you want to modify.
The following example demonstrates how to zoom a node while the mouse is hovering over it:
private static Region createRegion(String background) {
Region region = new Region();
region.setStyle("-fx-background-color:"+background);
region.setPrefSize(300, 100);
return region;
}
#Override
public void start(Stage primaryStage) {
GridPane gp = new GridPane();
// create background
gp.add(createRegion("green"), 0, 0);
gp.add(createRegion("dodgerblue"), 0, 1);
// create region to be zoomed
Region zoomRegion = createRegion("red");
GridPane.setFillWidth(zoomRegion, Boolean.FALSE);
GridPane.setFillHeight(zoomRegion, Boolean.FALSE);
zoomRegion.setPrefWidth(100);
Scale scale = new Scale();
zoomRegion.getTransforms().add(scale);
// keep pivot at bottom left corner
scale.pivotYProperty().bind(zoomRegion.heightProperty());
zoomRegion.hoverProperty().addListener((observable, oldValue, newValue) -> {
// adjust scale when hover state is changed
double scaleFactor = newValue ? 1.5 : 1;
scale.setX(scaleFactor);
scale.setY(scaleFactor);
});
gp.add(zoomRegion, 0, 1);
Scene scene = new Scene(gp);
primaryStage.setScene(scene);
primaryStage.show();
}

JavaFX trouble with fade transitions

I'm currently developing an app. It's visual structure is the following:
Only one Stage.
Only one Scene which has an ApplicationContainer's (my own class which
is basically a StackPane with a BorderPane inside of it with a
MenuBar on top, and the current page in it's center).
Multiple ApplicationLayout's
The ApplicationLayout has a Header and a Footer (footer not implemented yet) and looks like this:
I've managed to implement fadeIn / fadeOut transitions between the pages by setting a StackPane as the BorderPane's center, adding the page to it, and on top of that, a white VBox. So before I make the page switch I work with FadeTransitions of this white VBox.
I had to do it this way because setOpacity() wouldn't change the textfields or button opacities for some reason.
Now I'm trying to do the exact same thing for the header. So I setted a StackPane to the top, and added to it the header and a on top of it a "header coverer" which supposedly should do the trick just as before (can't modify the opacity property of the title, arrow or description because of CSS overriding).
But this time it's not working, if I set the opacity of the header coverer to anything but 0, the stuff in the header doesn't show.
What I want to acomplish is to fadeOut / FadeIn the components of the header but not the orange HBox.
EDIT: Added a minimal example where this doesn't work for me
public class Main extends Application {
private Boolean buttonPressed = false;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
BorderPane appWindow = new BorderPane();
appWindow.setStyle("-fx-alignment: center; -fx-padding: 30 0 0 30");
appWindow.setBackground(new Background(new BackgroundFill(Color.PERU, null, null)));
GridPane loginContainer = new GridPane();
appWindow.setCenter(loginContainer);
TextField username = new TextField();
PasswordField password = new PasswordField();
Label userNameDesc = new Label("Username");
Label passwordDesc = new Label("Password");
Button logInBtn = new Button("Log In");
logInBtn.setTranslateX(100);
logInBtn.setTranslateY(20);
logInBtn.setOnAction(event -> {
if (!buttonPressed) {
appWindow.getCenter().setOpacity(30);
buttonPressed = true;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
else {
appWindow.getCenter().setOpacity(100);
buttonPressed = false;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
});
loginContainer.addColumn(0, userNameDesc, passwordDesc);
loginContainer.addColumn(1, username, password);
loginContainer.add(logInBtn, 1, 2);
Scene scene = new Scene(appWindow, 300, 250);
stage.setScene(scene);
stage.show();
}
}
Pressing the "Log In" button should affect the Gridpane and Gridpane childs visual opacity, but it doesn't. It just prints the correct opacity values.
According to the documentation:
Opacity is specified as a value between 0 and 1. Values less than 0 are treated as 0, values greater than 1 are treated as 1.
So setting the value to 30 or to 100 has no effect: both are treated as fully opaque (i.e. they are clamped at 1).
Replacing
appWindow.getCenter().setOpacity(30);
with
appWindow.getCenter().setOpacity(0.3);
will make the center content partially transparent.

Change postion of a line to make a gauge javafx

I want to make half radial gauge. I've tried to put an arc of 180° and I put a line on it, and I tried to move this line to use this as an indicator of position.
I tried to move the line to different position in Scene Builder and it appears that it could works but when I tried to move with code it doesn't.
private Scanner sc;
public void deplacement_aiguille(){
sc = new Scanner(System.in);
double angle = sc.nextDouble();
String valangle = Double.toString(angle);
valeur_gisement.setText(valangle);
float xfin = (float) ((Math.cos(angle))*200);
float yfin = (float) ((Math.sin(angle)*200));
if(angle<90){
gisement.relocate(5,10);
gisement.setEndX(xfin);
gisement.setEndY(-yfin);
}
if (angle>90){
gisement.relocate(6,10);
gisement.setEndX(xfin);
gisement.setEndY(yfin);
}
if(angle==90){
gisement.setEndX(0);
gisement.setEndY(200);
}
if(angle==180){
gisement.setEndX(200);
gisement.setEndY(0);
}
if(angle==0){
gisement.relocate(5,10);
gisement.setEndX(-200);
gisement.setEndY(0);
}
}
With this code I want to move the line in my gridpane to the column number 5 and row number 10 when my angle is smaller than 90 and to the column number 6 and row 10 when angle is bigger than 90
I'm not sure if it's the good way to do it. So if you have any better idea I'll take it. But if it's the good way to do it would you help me to make it works.
Thanks
I'd put the Arc and the Line in a Pane (for absolute positioning) and use a Rotate transform to move the line.
IMO More important is to bind the Rotate to the input value. In my example I use a Slider for it:
public class Gauge extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Arc arc = new Arc();
arc.setCenterX(100);
arc.setCenterY(0);
arc.setRadiusX(100);
arc.setRadiusY(100);
arc.setStartAngle(0);
arc.setLength(180);
arc.relocate(0, 0);
double lineCenterX = 100d;
double lineCenterY = 100d;
Line line = new Line(lineCenterX, lineCenterY, 0, 100);
line.setStroke(Color.YELLOW);
Rotate rotate = new Rotate();
rotate.setPivotX(lineCenterX);
rotate.setPivotY(lineCenterY);
line.getTransforms().add(rotate);
Pane pane = new Pane();
pane.getChildren().addAll(arc, line);
Slider slider = new Slider();
rotate.angleProperty().bind(slider.valueProperty().multiply(1.8));
VBox vbox = new VBox(10);
vbox.getChildren().addAll(pane, slider);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Make a BorderPane region go over another

I've been trying for days and days now to get a BorderPane region go over another region...
The problem is as follow: My app is set in a BorderPane root, With:
A header in its TOP region
A menu in its LEFT region
The content, depending on the page, in it's CENTER
And an optional panel on its RIGHT region
That right region is the problem. It should appear/disappear when clicking on a "notification button" that is in the TOP region. So far so good. The thing is that the app doesn't use the RIGHT region, so I'm trying to make the RIGHT region that contains an AnchorPane go over the CENTER region. The normal state of the app is without the RIGHT region and I don't want to resize the whole app when opening the noitifications. Tried several things, such as:
When clicking the notification button, send the CENTER part toBack() and set the RIGHT width to the 300 wanted pixels
Sending the RIGHT region toFront()
Sending the whole BorderPane toFront()
None of them work, as they all either not show, or resize the center part which I don't want. I'd like the RIGHT to float above the CENTER region when the notification menu is showing.... Is there any way to do that? Or maybe another idea to trigger a container that would show above the CENTER part? Of course, I go design the panel in every CENTER pane and make it visible or not, but my app is about 15 different center windows so it would be really bad in terms of modifications...
I think you should not be trying to make the borderpane do this for you or you will end up with behavior you do not want like the center NOT resizing when the application is resized while the panel is visible.
Remember that JavaFX is really 3D. How about you try to wrap the BorderPane inside of an AnchorPane, GridPane or ScrollPane (whichever makes sense) instead of trying to get the right insert to do your thing. e.g. add an ScrollPane (your Slider) to the containing AnchorPane and bring that to the front and anchor it's top, right and bottom.
This should give you a right-aligned ScrollPane on top of your borderpane.
Then of course if you want it to be fancy with an animated slide you can try this out : https://gist.github.com/jewelsea/1437374
or this:
http://blog.physalix.com/javafx2-borderpane-which-slides-in-and-out-on-command/
Here is a very rough example to show the idea:
public class JavaFXApplication2 extends Application {
ScrollPane slider;
AnchorPane root;
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Slide in");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
root.getChildren().add(slider);
AnchorPane.setRightAnchor(slider, 0.);
AnchorPane.setTopAnchor(slider, 0.);
AnchorPane.setBottomAnchor(slider, 0.);
slider.toFront();
}
});
Label l = new Label();
l.setText("Test Label to Show inside content");
Label l2 = new Label();
l2.setText("Peek-a-Boo");
slider = new ScrollPane();
slider.setStyle("-fx-border-color: orangered;");
slider.setContent(l2);
root = new AnchorPane();
root.getChildren().add(btn);
root.getChildren().add(l);
AnchorPane.setRightAnchor(l, 0.);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

Resources