I have a pie chart where i have added a mouse listener using this guide:
Oracle guide to pie chart
However when i run my program and click on the chart it doesnt do anything.
I have tried to System.out.println(caption.getText()); and the text of the label is correct however the label is just not showing up.
My code is as following:
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", 13),
new PieChart.Data("Oranges", 25),
new PieChart.Data("Plums", 10),
new PieChart.Data("Pears", 22),
new PieChart.Data("Apples", 30));
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Imported Fruits");
((Group) scene.getRoot()).getChildren().add(chart);
final Label caption = new Label("");
caption.setTextFill(Color.DARKORANGE);
caption.setStyle("-fx-font: 24 arial;");
for (final PieChart.Data data : chart.getData()) {
data.getNode().addEventHandler(MouseEvent.MOUSE_PRESSED,
new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent e) {
caption.setTranslateX(e.getSceneX());
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
caption.setVisible(true);
}
});
}
stage.setScene(scene);
stage.show();
}
}
Can anyone tell me what i did wrong?
You forgot to add the label 'caption' to the list of children in your root node :-)
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", 13),
new PieChart.Data("Oranges", 25),
new PieChart.Data("Plums", 10),
new PieChart.Data("Pears", 22),
new PieChart.Data("Apples", 30));
final PieChart chart = new PieChart(pieChartData);
chart.setTitle("Imported Fruits");
final ObservableList<Node> children = ((Group) scene.getRoot()).getChildren();
children.add(chart);
final Label caption = new Label("");
caption.setTextFill(Color.DARKORANGE);
caption.setStyle("-fx-font: 24 arial;");
children.add(caption);
for (final PieChart.Data data : chart.getData()) {
data.getNode().addEventHandler(MouseEvent.MOUSE_PRESSED,
new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent e) {
caption.setTranslateX(e.getSceneX());
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
caption.setVisible(true);
}
});
}
stage.setScene(scene);
stage.show();
}
I have made the above change and can verify that it works (as depicted by the image below)
no need for that, you just have to add caption, here:
Change this line :((Group) scene.getRoot()).getChildren().addAll(chart);
to :((Group) scene.getRoot()).getChildren().addAll(chart,caption);
Related
I've been trying to code this Javafx gui program, however when ever Try to use the getValue() method it ends up saying "it can't find that symbol". Even if I try demos of using the method. How can i get this method to work, is there any other way I can get code to run when the user chooses a choice from the combobox?
not showing my imports, as they are a lot.
public class LogoMaster3000 extends Application {
BorderPane border;
HBox hbox;
Canvas can;
AnchorPane ap;
Scene scene;
Button shapesComboBox;
// Desktop desktop = Desktop.getDesktop();
TextField tx;
#Override
public void start(Stage primaryStage) {
border = new BorderPane();
hbox = addHBox();
border.setTop(hbox);
border.setLeft(addVBox());
addStackPane(hbox); // Add stack to HBox in top region
can = new Canvas();
can.setStyle("-fx-background-color: #E8EACD");
AnchorPane wrapperPane = new AnchorPane();
border.setCenter(wrapperPane);
scene = new Scene(border, 1000, 600);
primaryStage.setTitle("LogoMaker 3000");
primaryStage.setScene(scene);
primaryStage.show();
shapesComboBox.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
if (shapesComboBox.getValue == "Square"){
Rectangle square = new Rectangle(50, 50);
square.setFill(Color.BLACK);
DragResizeMod.makeResizable(square, null);
wrapperPane.getChildren().add(square);
}
if (shapesComboBox.getValue == "Rectangle"){
Rectangle rectangle = new Rectangle(50, 50);
rectangle.setFill(Color.BLACK);
DragResizeMod.makeResizable(rectangle, null);
wrapperPane.getChildren().add(rectangle);
}
if (shapesComboBox.getValue == "Triangle"){
Polygon polygon = new Polygon();
polygon.getPoints().addAll(new Double[]{
75, 0,
50, 50,
100, 100
})
polygon.setFill(Color.BLACK);
DragResizeMod.makeResizable(polygon, null);
wrapperPane.getChildren().add(polygon);
}
if (shapesComboBox.getValue == "Circle"){
Circle circle = new Circle(100,100,50);
circle.setFill(Color.BLACK);
DragResizeMod.makeResizable(circle, null)
wrapperPane.getChildren().add(circle);
}
}
}
);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
public void addStackPane(HBox hb) {
StackPane stack = new StackPane();
Rectangle helpIcon = new Rectangle(30.0, 25.0);
helpIcon.setFill(new LinearGradient(0,0,0,1, true, CycleMethod.NO_CYCLE,
new Stop[]{
new Stop(0,Color.web("#4977A3")),
new Stop(0.5, Color.web("#B0C6DA")),
new Stop(1,Color.web("#9CB6CF")),}));
helpIcon.setStroke(Color.web("#D0E6FA"));
helpIcon.setArcHeight(3.5);
helpIcon.setArcWidth(3.5);
Text helpText = new Text("?");
helpText.setFont(Font.font("Verdana", FontWeight.BOLD, 18));
helpText.setFill(Color.WHITE);
helpText.setStroke(Color.web("#7080A0"));
stack.getChildren().addAll(helpIcon, helpText);
stack.setAlignment(Pos.CENTER_RIGHT); // Right-justify nodes in stack
StackPane.setMargin(helpText, new Insets(0, 10, 0, 0)); // Center "?"
hb.getChildren().add(stack); // Add to HBox from Example 1-2
HBox.setHgrow(stack, Priority.ALWAYS); // Give stack any extra space
}
public VBox addVBox() {
VBox vbox = new VBox();
vbox.setPadding(new Insets(10));
vbox.setSpacing(8);
Text title = new Text("Logo Maker");
title.setFont(Font.font("Arial", FontWeight.BOLD, 14));
vbox.getChildren().add(title);
final ComboBox shapesComboBox = new ComboBox();
shapesComboBox.getItems().addAll(
"Square",
"Rectangle",
"Triangle",
"Circle",
"Pyramid",
"Cube",
"Sphere"
);
shapesComboBox.setPromptText("Shapes");
shapesComboBox.setMaxWidth(Double.MAX_VALUE);
vbox.getChildren().add(shapesComboBox);
return vbox;
}
}
Is it possible to do a simple background "flash" effect with a gradual fade on an arbitrary Node/Region/Pane?
I just want to show a subtle/brief red/white "flash" effect on a VBox (containing a label) to draw attention to it when the label's value changes.
Edit: All examples of this nature I've found so far seem to use a "Shape" (which is a Node), but of course a VBox or a Pane aren't a Shape - so that doesn't help me too much. Calling getShape() on the VBox just returns a null, so that's no help (I guess layout code hasn't been executed yet).
Edit 2:
This ALMOST works, but this dang effect seems to be completely overwriting (I think) everything in the VBox, including the text Label.
ColorInput effect = new ColorInput(0, 0, 900, 25, Paint.valueOf("#FFDDDD"));
Timeline flash = new Timeline(
new KeyFrame(Duration.seconds(0.4), new KeyValue(effect.paintProperty(), Paint.valueOf("#EED9D9"))),
new KeyFrame(Duration.seconds(0.8), new KeyValue(effect.paintProperty(), Paint.valueOf("#E0DDDD"))),
new KeyFrame(Duration.seconds(1.0), new KeyValue(effect.paintProperty(), Paint.valueOf("#DDDDDD"))));
vbox.setEffect(effect);
flash.setOnFinished(e -> vbox.setEffect(null));
flash.play();
Best way would be to provide a custom animation, like this (elaborating on fabian's answer):
#Override
public void start(Stage primaryStage) {
Label label = new Label("Bla bla bla bla");
Button btn = new Button("flash");
VBox box = new VBox(10, label, btn);
box.setPadding(new Insets(10));
btn.setOnAction((ActionEvent event) -> {
//**************************
//this animation changes the background color
//of the VBox from red with opacity=1
//to red with opacity=0
//**************************
final Animation animation = new Transition() {
{
setCycleDuration(Duration.millis(1000));
setInterpolator(Interpolator.EASE_OUT);
}
#Override
protected void interpolate(double frac) {
Color vColor = new Color(1, 0, 0, 1 - frac);
box.setBackground(new Background(new BackgroundFill(vColor, CornerRadii.EMPTY, Insets.EMPTY)));
}
};
animation.play();
});
Scene scene = new Scene(box, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
You could animate a effect, e.g. DropShadow:
#Override
public void start(Stage primaryStage) {
Label label = new Label("Bla bla bla bla");
DropShadow shadow = new DropShadow();
shadow.setColor(Color.RED);
shadow.setSpread(0.75);
Timeline shadowAnimation = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(shadow.radiusProperty(), 0d)),
new KeyFrame(Duration.seconds(0.15), new KeyValue(shadow.radiusProperty(), 20d)));
shadowAnimation.setAutoReverse(true);
shadowAnimation.setCycleCount(2);
Button btn = new Button("flash");
btn.setOnAction((ActionEvent event) -> {
Node target = label;
target.setEffect(shadow);
shadowAnimation.setOnFinished(evt -> target.setEffect(null));
shadowAnimation.play();
});
VBox box = new VBox(10, label, btn);
box.setPadding(new Insets(10));
Scene scene = new Scene(box, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
You can create a fake shape and use the FillTransition Interpolator to apply the shape's fill to the control background.
public static void AnimateBackgroundColor(Control control, Color fromColor,Color toColor,int duration)
{
Rectangle rect = new Rectangle();
rect.setFill(fromColor);
FillTransition tr = new FillTransition();
tr.setShape(rect);
tr.setDuration(Duration.millis(duration));
tr.setFromValue(fromColor);
tr.setToValue(toColor);
tr.setInterpolator(new Interpolator() {
#Override
protected double curve(double t) {
control.setBackground(new Background(new BackgroundFill(rect.getFill(), CornerRadii.EMPTY, Insets.EMPTY)));
return t;
}
});
tr.play();
}
I tried using this method to print show a popup with label "THAT'S IT" and I don't want to use the Popup class
public void showStage(Stage Owner){
HBox hBox = new HBox();
hBox.getChildren().add(new Label("THAT'S IT"));
Scene sc = new Scene(hBox);
Stage popup = new Stage();
popup.setScene(sc);
popup.setWidth(400);
popup.setHeight(100);
popup.initOwner(owner);
popup.initModality(Modality.WINDOW_MODAL);
popup.show();
}
and then I call the showStage() method from the start method
public void start(Stage primaryStage) {
Label lb = new Label();
btn.setText("Say 'Hello World'");
btn.setOnAction(e->{
lb.setText("hello everyone");showStage(primaryStage);
});
But the output of the code :
Why don't you use a dialog?
You can use it in your main controller class without creating an other stage for instance like this:
Dialog dialogQtPrescription = new Dialog();
dialogQtPrescription.setTitle("yourTitle");
dialogQtPrescription.setHeaderText("yourHeadertext");
dialogQtPrescription.initModality(Modality.WINDOW_MODAL);
dialogQtPrescription.initOwner(mainStage);
dialogQtPrescription.initStyle(StageStyle.UTILITY);
GridPane gridDialogPrescription = new GridPane();
gridDialogPrescription.setHgap(10);
gridDialogPrescription.setVgap(10);
gridDialogPrescription.add(new Label(bundle.getString("quantityPrescription.title")), 0, 0);
TextField txtQtPrescr = new TextField();
ButtonType buttonTypeNo = new ButtonType("no");
ButtonType buttonTypeYes = new ButtonType("yes");
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
dialogQtPrescription.getDialogPane().getButtonTypes().addAll(buttonTypeNo,buttonTypeYes, buttonTypeCancel);
txtQtPrescr.setPrefWidth(100);
gridDialogPrescription.add(txtQtPrescr, 1, 0);
dialogQtPrescription.getDialogPane().setContent(gridDialogPrescription);
Optional<ButtonType> result = dialogQtPrescription.showAndWait();
this is just a stack of code from a project but i hope it make you to understand my idea.
here's better explained: http://code.makery.ch/blog/javafx-dialogs-official/
You can use this in order to make a Popup on any Screen in JavaFX
public void popup() {
final Stage dialog = new Stage();
dialog.setTitle("Confirmation");
Button yes = new Button("Yes");
Button no = new Button("No");
Label displayLabel = new Label("What do you want to do ?");
displayLabel.setFont(Font.font(null, FontWeight.BOLD, 14));
dialog.initModality(Modality.NONE);
dialog.initOwner((Stage) tableview.getScene().getWindow());
HBox dialogHbox = new HBox(20);
dialogHbox.setAlignment(Pos.CENTER);
VBox dialogVbox1 = new VBox(20);
dialogVbox1.setAlignment(Pos.CENTER_LEFT);
VBox dialogVbox2 = new VBox(20);
dialogVbox2.setAlignment(Pos.CENTER_RIGHT);
dialogHbox.getChildren().add(displayLabel);
dialogVbox1.getChildren().add(yes);
dialogVbox2.getChildren().add(no);
yes.addEventHandler(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
// inside here you can use the minimize or close the previous stage//
dialog.close();
}
});
no.addEventHandler(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
dialog.close();
}
});
dialogHbox.getChildren().addAll(dialogVbox1, dialogVbox2);
Scene dialogScene = new Scene(dialogHbox, 500, 40);
dialogScene.getStylesheets().add("//style sheet of your choice");
dialog.setScene(dialogScene);
dialog.show();
}
I am building a javaFX application.
The example program which is online working well: http://www.java2s.com/Tutorials/Java/JavaFX/1010__JavaFX_Timeline_Animation.htm
I changed it a bit:
I want to have these nice moving circles in the background. That's why I made these tricks:
Main.java:
#Override
public void start(Stage primaryStage) {
try {
// load the FXML resource
FXMLLoader loader = new FXMLLoader(getClass().getResource("Dashboard.fxml"));
// store the root element so that the controllers can use it
StackPane root = new StackPane();
Pane bgRoot = new Pane();
GridPane userRoot = (GridPane) loader.load();
// create and style a scene
Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
BackgroundScene bgScene = new BackgroundScene(root, bgRoot, primaryScreenBounds.getWidth(),
primaryScreenBounds.getHeight(), Color.BLACK);
// TODO CSS load:
// bgScene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
// create the stage with the given title and the previously created
// scene
primaryStage.setFullScreen(true);
primaryStage.setMaximized(true);
primaryStage.setResizable(false);
primaryStage.setMinWidth(primaryScreenBounds.getWidth());
primaryStage.setMinHeight(primaryScreenBounds.getHeight());
primaryStage.setScene(bgScene);
root.getChildren().add(bgRoot);
root.getChildren().add(userRoot);
// show the GUI
primaryStage.show();
userRoot.setPrefHeight(root.getHeight());
userRoot.setPrefWidth(root.getWidth());
} catch (Exception e) {
e.printStackTrace();
}
}
In the above code:
I have a stage with a stack pane.
There is a Pane on the StackPane with the Circles
On that there is a GridPane for controllers.
I made my own Scene as BackgroundScene:
public class BackgroundScene extends Scene {
private Pane bgRoot;
public BackgroundScene(Parent root, Pane bgRoot, double width, double height, Color color) {
super(root, width, height, color);
this.bgRoot = bgRoot;
makeGreenCircleAnimation();
}
public void makeGreenCircleAnimation() {
Group circles = new Group();
for (int i = 0; i < 30; i++) {
Circle circle = new Circle(Math.random() * this.getWidth(), Math.random() * this.getHeight(),
150, Color.web("white", 0.05));
circle.setStrokeType(StrokeType.OUTSIDE);
circle.setStroke(Color.web("white", 0.16));
circle.setStrokeWidth(4);
circles.getChildren().add(circle);
}
circles.setEffect(new BoxBlur(10, 10, 3));
Rectangle colors = new Rectangle(this.getWidth(), this.getHeight(),
new LinearGradient(0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE,
new Stop[] { new Stop(0, Color.web("#00ff00")), new Stop(0.14, Color.web("#11ee11")),
new Stop(0.28, Color.web("#22dd22")), new Stop(0.43, Color.web("#33cc33")),
new Stop(0.57, Color.web("#44bb44")), new Stop(0.71, Color.web("#55aa55")),
new Stop(0.85, Color.web("#669966")), new Stop(1, Color.web("#778877")), }));
Group blendModeGroup = new Group(
new Group(new Rectangle(this.getWidth(), this.getHeight(), Color.DARKGREEN), circles), colors);
colors.setBlendMode(BlendMode.OVERLAY);
bgRoot.getChildren().add(blendModeGroup);
Timeline timeline = new Timeline();
makeAnimation(circles, timeline);
timeline.play();
timeline.setOnFinished(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
makeAnimation(circles, timeline);
timeline.play();
}
});
}
void makeAnimation(Group group, Timeline timeline) {
timeline.getKeyFrames().clear();
for (Node node : group.getChildren()) {
timeline.getKeyFrames()
.addAll(new KeyFrame(Duration.ZERO, // set start
// position at 0
new KeyValue(node.translateXProperty(), node.getLayoutX() + node.getTranslateX()),
new KeyValue(node.translateYProperty(), node.getLayoutY() + node.getTranslateY())),
new KeyFrame(new Duration(4000), // set end position at
// 40s
new KeyValue(node.translateXProperty(), Math.random() * this.getWidth()),
new KeyValue(node.translateYProperty(), Math.random() * this.getHeight())));
}
}
}
It contains the code from the tutorial (with minor changes).
I add the circles and everything to the Pane not to a Group (as in
the online example)
The problem is that it is seams to be moving:
The circles are moving to the right (always)
If I change something in the code:
Main.java (instantiating my scene):
BackgroundScene bgScene = new BackgroundScene(root, root, primaryScreenBounds.getWidth(),
primaryScreenBounds.getHeight(), Color.BLACK);
(so giving the circles to the StackPane)
This happens:
You can download the eclipse project:
https://www.dropbox.com/s/dovae0hxdtsnsdo/Test.7z?dl=0
Do you know what is the problem?
Or can you suggest something how I can put the circles nicely behind the button?
I am new to JavaFX, here I want to create a new Stage and one TextArea inside it at the run-time and I want to pass a line to that text area and update it continuously.
Can anybody please give me the example of doing this?
Hyperlink link = new Hyperlink("TEST");
link.setOnAction(new EventHandler<ActionEvent>() {
#override public void handle(ActionEvent e) {
Stage stage = new Stage();
TextArea text = new TextArea():
VBox vbox = new VBox();
Button close = new Button();
close.setText("Close");
close.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
stage.close();
}
});
vbox.getChildren().addAll(text, close);
Scene scene = new Scene(vbox);
stage.setScene(scene);
stage.setMinWidth(100);
stage.setMinHeight(100);
stage.show();
// ...
text.setText("update");
}
});