Is there a way how I can make something like a FillTransition for a Label?
I basically just want to change the text color of the Label in an animated way.
Thank you already!
A simple solution would be using a Text node instead of a Label. Text extends Shape and therefore can be used with a FillTransition. On the other hand you loose the possibility of adding a background and the ellipsis functionality.
If you want to keep using a Label, I recommend animating the textFill property using a Timeline.
Example:
#Override
public void start(Stage primaryStage) throws Exception {
Color fromColor = Color.BLACK;
Color toColor = Color.ORANGE;
Label label = new Label("hello world!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(label.textFillProperty(), fromColor)),
new KeyFrame(Duration.seconds(10), new KeyValue(label.textFillProperty(), toColor))
);
timeline.play();
Scene scene = new Scene(new StackPane(label));
primaryStage.setScene(scene);
primaryStage.show();
}
Related
I have two scenes A and B and a stage.
If I'm in scene A, and change the stage width / height, it will update the UI to scale it to the new stage dimensions.
However if from there I switch to scene B, the UI in scene B will not be updated till I force a update by doing something like resizing the screen or opening and closing the stage.
Is there a way to update all scenes when the stage width / height is changed? Since only one scene can be set to the stage at one time the current changes are not applying automatically to all scenes.
Here's a minimal reproduced example.
#Override
public void start(Stage stage) throws Exception {
stage.setWidth(400);
stage.setHeight(400);
Scene scene1, scene2;
BorderPane layout1 = new BorderPane();
Button buttontosecond = new Button("go to second page");
layout1.setCenter(buttontosecond);
scene1 = new Scene(layout1, stage.getWidth(), stage.getHeight());
BorderPane layout2 = new BorderPane();
Button buttonsize = new Button("change size");
Button buttontomain = new Button("back to main");
VBox vbox = new VBox(buttonsize, buttontomain);
vbox.setAlignment(Pos.CENTER);
layout2.setCenter(vbox);
scene2 = new Scene(layout2, stage.getWidth(), stage.getHeight());
buttontomain.setOnAction(actionEvent -> {stage.setScene(scene1);});
buttontosecond.setOnAction(actionEvent -> {stage.setScene(scene2);});
buttonsize.setOnAction(actionEvent -> {stage.setWidth(200);stage.setHeight(200);});
stage.setScene(scene1);
stage.show();
}
DO not do scene switching in this way. Instead implement a single scene root-switching system as shown in the answer to this post. I did not manage to get the code above to work, but I found that the reason for this was my dual monitor setup. When dragging the game window into the other monitor it worked fine.
I'm trying to create a new Stage when a button is pressed.
It works but the problem is that I'd like this Stage to be fully transparent and lets us see what's behind the screen.
Code
Dimension Sizescreen = Toolkit.getDefaultToolkit().getScreenSize();
//Main stage with option menu
Pane window = new Pane();
Scene scene = new Scene(window);
stage.setTitle("Notification Extender");
//Create the button SetLooker
Button SetLooker = new Button("Set Looker");
//Add a Event when pressed
SetLooker.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
//Create a sub-Stage
Pane subwindow = new Pane();
Scene subscene = new Scene(subwindow);
Stage substage = new Stage();
substage.setTitle("Notification Extender");
//Set this subStage Transparent
substage.initStyle(StageStyle.TRANSPARENT);
subscene.setFill(Color.TRANSPARENT);
substage.setWidth(Sizescreen.getWidth());
substage.setHeight(Sizescreen.getHeight());
substage.setX(0);
substage.setY(0);
//Create a a graphique element
Rectangle redrec = new Rectangle(120,40,50,50);
redrec.setStroke(Color.RED);
redrec.setStrokeWidth(2);
redrec.setFill(Color.TRANSPARENT);
//Add the graphique element to the sub-stage
subwindow.getChildren().add(redrec);
//Show the sub-stage
substage.setScene(subscene);
substage.show();
}
});
//Add the button to the main stage
window.getChildren().add(SetLooker);
//Show the main stage
stage.setScene(scene);
stage.show();
The problem is that when I press the button it shows the stage but it's not transparent at all it's completely white.
I've also tried to change the main Stage, but I cannot change it once it has been shown.
You also need to remove the background from the root of your new scene:
subwindow.setBackground(null);
I don't want to use AWT.
I was using FontMetrics.computeStringWidth() but is gone in JDK 10 breaking my app. Is there an alternative that doesn't require bringing a new framework (I'm using javafx)
You can use Text and get the size from the boundsInLocal property. (The Text node does not need to be attached to a scene for this to work.)
The following code keeps the width of the Rectangle the same as the size of the Text.
#Override
public void start(Stage primaryStage) throws Exception {
Text text = new Text();
TextField textField = new TextField();
Rectangle rect = new Rectangle(0, 20);
textField.textProperty().addListener((o, oldValue, newValue) -> {
text.setText(newValue);
rect.setWidth(text.getBoundsInLocal().getWidth());
});
Scene scene = new Scene(new VBox(textField, text, rect), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
Can a set of lines be drawn on a text area component which would look like this .
I then need to be able to type in text over them . These lines also need to be erased and redrawn
Consider drawing lines on a Pane like so:
public class StageTest extends Application{
private static final double WIDTH = 100, HEIGHT = 60;
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("Test Stage");
Label label = new Label("Some text ");
label.setStyle("-fx-background-color:TRANSPARENT");
label.setAlignment(Pos.CENTER);
label.setPrefSize(WIDTH, HEIGHT);
Pane linesPane = getPane(label);
StackPane root = new StackPane(linesPane, label);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private Pane getPane(Label label) {
Pane pane = new Pane();
pane.setStyle("-fx-background-color:WHITE");
Line blueLine = new Line();
blueLine.setStroke(Color.BLUE);
blueLine.startXProperty().bind(label.layoutXProperty());
blueLine.startYProperty().bind(label.layoutYProperty().add(label.heightProperty().multiply(.333)));
blueLine.endXProperty().bind(label.layoutXProperty().add(label.widthProperty()));
blueLine.endYProperty().bind(label.layoutYProperty().add(label.heightProperty().multiply(.333)));
Line redLine = new Line();
redLine.setStroke(Color.RED);
redLine.startXProperty().bind(label.layoutXProperty());
redLine.startYProperty().bind(label.layoutYProperty().add(label.heightProperty().multiply(.666)));
redLine.endXProperty().bind(label.layoutXProperty().add(label.widthProperty()));
redLine.endYProperty().bind(label.layoutYProperty().add(label.heightProperty().multiply(.666)));
pane.getChildren().addAll(blueLine, redLine);
return pane;
}
public static void main(String[] args) {
launch(args);
}
}
You may want to look at using the background property of TextArea.
new TextArea().setBackground(new Background(new BackgroundImage(myImage,BackgroundRepeat.NO_REPEAT,BackgroundRepeat.NO_REPEAT,BackgroundPosition.CENTER,BackgroundSize.DEFAULT)));
This code here is assuming you can get those lines as an image.
You can find more info for backgrounds here: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/Background.html
If you want the background image to change and be dynamic for your current needs, you have two options.
Just use a Canvas for the whole project. Paint the lines onto the canvas first, and then paint the letters on top of this. This could be better as it would allow you to customize your project to however you would like it, but it would take a bit more code and thinking to do.
Use the TextArea, and for the BackgroundImage, use a Snapshot of another Canvas. You can use a Canvas to draw the lines however you would like, and then convert it to an image using Snapshot.
WritableImage i = canvas.snapshot(new SnapshotParameters(), null);
Then, using this image, you can use that as the background of the TextArea by using BackgroundImage.
I'm struggling to display text in a simple javafx application, and I'm struggling to see why it's happening. Here's my code:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
//Declarations
Pane root = new Pane();
Scene scene = new Scene(root, 960, 600);
javafx.scene.canvas.Canvas background = new Canvas(3840, 2160);
StackPane infoPane = new StackPane();
Text test = new Text("Hello");
test.setY(500);
test.setX(500);
root.getChildren().add(test);
//Stage Setting
primaryStage.setScene(scene);
primaryStage.setTitle("Test application");
primaryStage.setFullScreen(true);
primaryStage.setFullScreenExitHint("Press escape to exit fullscreen");
primaryStage.show();
//javafx.scene.image.Image icon = new Image("Sample/Test.png");
//primaryStage.getIcons().add(icon);
//Parent and child declarations
infoPane.getChildren().add(test);
//Styling
//Background
StackPane backgroundHolder = new StackPane();
backgroundHolder.setStyle("-fx-background-color: #0053A8");
backgroundHolder.getChildren().add(background);
root.getChildren().add(backgroundHolder);
}
The idea is to have an application with a blue background, that has different text fields on it. Thanks for any and all help!
You add the test node to your root Pane, but then you add it also to infoPane. Since a node can only appear once in the scene graph, you are essentially removing it from the root pane before you can see it.
Note that you never add infoPane to your scene graph.
I suggest you read this tutorial, and maybe try a few simple layouts with Scene Builder.