This is my first question here so donĀ“t be to mad at me if something is wrong. I am currently programming an idle like game for java with help of JavaFx.
The code here under was written with eclipse mars and JavaFx. Eclipse shows to me that the code is right but when I want to start the program it throws this block of error messages:
public class Main extends Application{
private static final Color color = Color.web("#464646");
Button button3 = new Button("D");
DropShadow shadow = new DropShadow();
Label label = new Label();
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception{
Scene scene = new Scene(new Group());
primaryStage.setTitle("Button Sample");
primaryStage.setWidth(300);
primaryStage.setHeight(190);
label.setFont(Font.font("Times New Roman", 22));
label.setTextFill(color);
Image imageDecline = new Image(getClass().getResourceAsStream("../not.png"));
Image imageAccept = new Image(getClass().getResourceAsStream("../ok.png"));
VBox vbox = new VBox();
vbox.setLayoutX(20);
vbox.setLayoutY(20);
HBox hbox1 = new HBox();
HBox hbox2 = new HBox();
Button button1 = new Button("Accept");
button1.setStyle("-fx-font: 22 arial; -fx-base: #b6e7c9;");
button1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
label.setText("Accepted");
}
});
Button button2 = new Button("Accept");
button2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
label.setText("Accepted");
}
});
button3.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
label.setText("Declined");
}
});
button3.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
button3.setEffect(shadow);
}
});
button3.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
button3.setEffect(null);
}
});
hbox1.getChildren().add(button2);
hbox1.getChildren().add(button3);
hbox1.getChildren().add(label);
hbox1.setSpacing(10);
hbox1.setAlignment(Pos.BOTTOM_CENTER);
Button button4 = new Button();
button4.setGraphic(new ImageView(imageAccept));
button4.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
label.setText("Accepted");
}
});
Button button5 = new Button();
button5.setGraphic(new ImageView(imageDecline));
button5.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
label.setText("Declined");
}
});
hbox2.getChildren().add(button4);
hbox2.getChildren().add(button5);
hbox2.setSpacing(25);
vbox.getChildren().add(button1);
vbox.getChildren().add(hbox1);
vbox.getChildren().add(hbox2);
vbox.setSpacing(10);
((Group) scene.getRoot()).getChildren().add(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}}
I hope anyone here has a hint or a solution for this problem :) Would be very nice from you.
Best Greetings,
Mike
I think your problem has to do with the input streams you use for creating your Image objects:
... = new Image(getClass().getResourceAsStream("../not.png"));
When I start your application in Eclipse, I get an InvocationTargetException as well. It is caused by a NullPointerException because the PNG files cannot be found.
Try to start your application without creating the Image objects and see if you still get any exceptions.
Related
I am using Javafx8 and lets say i have created many ui items (like buttons and so on...). I thought its a good idea to put all EventHandler for these buttons into a separates class. My question is: How can i get access from an EventHandler to any button, e.g. to diable it or to manipulate it on any other way.
Here is a minimum example with two buttons and a separate class for EventHandlers
Let's say this is my Start class:
public class App extends Application
{
#Override
public void start(Stage primaryStage) throws Exception {
Button b1 = new Button();
b1.setOnAction(ListenerClass.createB1Event());
Button b2 = new Button();
b2.setOnAction(ListenerClass.createB2Event());
VBox vbox = new VBox(b1, b2);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main( String[] args )
{
Application.launch(args);
}
}
And my (separate) listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createB1Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Deactivate B1
//Activate B2
}
};
}
public static EventHandler<ActionEvent> createB2Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Activate B1
//Dectivate B2
}
};
}
}
Thanks
So based on your principal. You want the button that is located in a vbox and got pressed to be disabled and all other buttons from that vbox to be enabled.
And your problem is how to find button that got pressed.
You need to use ActionEvent.getSource() method.
Heres how I'd code it....
This is Start class:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox vbox = new VBox();
Button b1 = addNewButton("Button1",vbox);
Button b2 = addNewButton("Button2",vbox);
Button b3 = addNewButton("Button3",vbox);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static Button addNewButton(String label, VBox ownerVBox){
Button button = new Button(label);
ownerVBox.getChildren().add(button);
button.setOnAction(ListenerClass.createBEvent());
return button;
}
public static void main(String[] args) {
launch(args);
}
}
Listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createBEvent() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
Button b = (Button) t.getSource();
VBox vbox =(VBox) b.getParent();
vbox.getChildren().forEach(button-> {
button.setDisable(false);
});
b.setDisable(true);
}
};
}
}
I'm making a grocery list app, and it has the feature to add items to the list(a tableview) along with the # of items and price. THe thing is, it works(because the tableview doesnt say "No content in table") But the table is blank. Any suggestions?
Code:
package listproject;
public class Main extends Application{
public Node getNodeByRowColumnIndex(final int row,final int column,GridPane gridPane) {
Node result = null;
ObservableList<Node> childrens = gridPane.getChildren();
for(Node node : childrens) {
if(gridPane.getRowIndex(node) == row && gridPane.getColumnIndex(node) == column) {
result = node;
break;
}
}
return result;
}
ObservableList<Product> data =
FXCollections.observableArrayList(
);
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Grocery List");
primaryStage.setWidth(450);
primaryStage.setHeight(800);
//menu buttons
Button addLinkMain = new Button("Add an Item");
Button addLinkTitle = new Button("Add an Item");
Button mainLinkAdd = new Button("Back");
Button mainLinkTitle = new Button("Back");
Button addItem = new Button("Add");
Button setTitleMenu = new Button("Set Title");
Button setTitleAdd = new Button("Set Title");
Button clear = new Button("Clear");
//items for the item addition screen
TextField title = new TextField("Name");
TextField quantity = new TextField("#");
TextField price = new TextField("$");
HBox addBox = new HBox();
BorderPane addBorder = new BorderPane();
HBox addMenu = new HBox();
//mainScene items
BorderPane pane = new BorderPane();
HBox mainscenemenu=new HBox();
TableView<Product> tableview = new TableView<Product>();
//tableview items
TableColumn itemTitle=new TableColumn("Product");
TableColumn itemQuantity=new TableColumn("Quantity");
TableColumn itemPrice=new TableColumn("Price");
//settitle items
TextField listTitle= new TextField("Rename the List");
Button setTittle = new Button("Set List Title");
BorderPane setTitlePane=new BorderPane();
StackPane setTitleFieldContainer=new StackPane();
HBox setTitleOwnMenu = new HBox();
//Scene declaration
Scene mainScene = new Scene(pane);
primaryStage.setScene(mainScene);
Scene addScene = new Scene(addBorder);
Scene setTitleScene = new Scene(setTitlePane);
//Main Scene
pane.setCenter(tableview);
pane.setBottom(mainscenemenu);
tableview.getColumns().addAll(itemTitle,itemQuantity,itemPrice);
mainscenemenu.getChildren().addAll(setTitleMenu,clear,addLinkMain);
tableview.setItems(data);
//Item Addition Scene
addBox.getChildren().addAll(title,quantity,price);
addMenu.getChildren().addAll(mainLinkAdd,addItem,setTitleAdd);
addBorder.setCenter(addBox);
addBorder.setBottom(addMenu);
//Set Title Scene
setTitleFieldContainer.getChildren().addAll(listTitle);
setTitleOwnMenu.getChildren().addAll(addLinkTitle,setTittle,mainLinkTitle);
setTitlePane.setCenter(setTitleFieldContainer);
setTitlePane.setBottom(setTitleOwnMenu);
//Menu Button Event Handlers
addLinkMain.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(addScene);
}
});
addLinkTitle.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(addScene);
}
});
mainLinkAdd.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(mainScene);
}
});
mainLinkTitle.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(mainScene);
}
});
setTitleMenu.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(setTitleScene);
}
});
setTitleAdd.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
primaryStage.setScene(setTitleScene);
}
});
//Adding an Item to the List *unfinished
addItem.setOnAction(new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
data.add(new Product(title.getText(),quantity.getText(),price.getText()));
}
});
//Changing the Title of The List
setTittle.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
primaryStage.setTitle(listTitle.getText());
}
});
//Clearing the List
clear.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
tableview.getItems().clear();
}
});
//Show the Stage
primaryStage.show();
}
public static void main(String[] args){
launch(args);
}
}
You never set the cellValueFactorys for the table's columns. You need to do this to specify the part of the items that should be displayed in the column.
An example with anonymus classes as cellValueFactorys can be found here.
Using PropertyValueFactory could reduce the amount of code needed. More about this here.
A tutorial can be found here: https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm
I have a TilePane that lists images from different directories on my hard disk. I would like, when an image on the TilePane is clicked:
To open the folder containing the image,
To open the image, for example, with the default program set to open that type of image file.
What I have so far only gives me something like ImageResources/faviicon.png when an image is clicked.
Is there any way I can use, for example, ImageResources/faviicon.png to do 1. and 2. above? Thank you all.
This is the Class I have:
public class TilePaneExample extends Application {
#Override
public void start(Stage primaryStage) {
VBox root = new VBox(30);
String[] imageResources = new String[]{
//loading images
"ImageResources/facebook.png",
"ImageResources/faviicon.png",
"ImageResources/jquery-logo.png",
"ImageResources/linkedin_32.png",
"ImageResources/loading1.png",
"ImageResources/twitter.png",
"ImageResources/twitter_32.png",
"ImageResources/wp.png",};
VBox vb = new VBox(20);
Text text4Tile = new Text("Images in TilePane");
text4Tile.setFont(Font.font("Calibri", FontWeight.BOLD, 30));
text4Tile.setUnderline(true);
VBox.setMargin(text4Tile, new Insets(10, 0, 0, 10));
//creating Flow Pane
TilePane tilePane = new TilePane();
tilePane.setHgap(5);
tilePane.setVgap(5);
for (final String imageResource : imageResources) {
Image image = new Image(getClass().getResourceAsStream(imageResource));
ImageView imageView = new ImageView(image);
imageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("You clicked: " + imageResource);
}
});
tilePane.getChildren().add(imageView);
}
vb.getChildren().addAll(text4Tile, tilePane);
root.getChildren().addAll(vb);
primaryStage.setTitle("TilePane Example");
Scene scene = new Scene(root, 300, 150);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Update:
Following DarkDarker's advice, I did this:
imageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
try {
System.out.println("You clicked: " + imageResource);
File f = new File(imageResource);
System.out.println(f.getAbsolutePath());
Desktop.getDesktop().open(f.getParentFile());
} catch (IOException ex) {
Logger.getLogger(TilePaneExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
I, however, get this error:
java.lang.IllegalArgumentException: The file: ImageResources doesn't exist.
at java.awt.Desktop.checkFileValidation(Desktop.java:209)
at java.awt.Desktop.open(Desktop.java:270)
for (final String imageResource : imageResources) {
String imagePath = getClass().getResource(imageResource).toExternalForm();
ImageView imageView = new ImageView(new Image(imagePath));
imageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("You clicked: " + imagePath);
File imageFile = new File(imagePath);
Desktop.getDesktop().open(imageFile.getParentFile()); // open a folder in explorer
Desktop.getDesktop().open(imageFile); // open file with system preferred program
}
});
tilePane.getChildren().add(imageView);
}
I am new to stackoverflow and also to Java programming, though I do have some small programming background.
I am building a little program using JavaFX 8.0.0-b132 and JavaSE 8...
The program has a GUI and this GUI has a ChoiceBox. The architecture for the layout is:
AnchorPane - VBox - TitledPane - GridPane - HBox - ChoiceBox
I have modified the ChoiceBox extensively using CSS.
Everything is working as it should except for one problem:
When I start the program and open the ChoiceBox (per mouse click or with show()) for the first time, it will display it's ContextMenu at the bottom edge as it should; however, when I close and open it again (with mouse or programmatically) it will display the ContextMenu on top of the ChoiceBox open-button (wrong y position), such that the bottom of the currently selected cell coincides with the bottom of the open-button (meaning it will change position after I select another cell and open it again).
How do I prevent this and make the ContextMenu appear always at the bottom as it does at first?
Here is a snippet of the GUI part of the program with the affected control:
EDIT: problem solved: apparently this behavior is the intended ChoiceBox behavior; I posted in the JavaFX forums that it would be better to make the popup behave like that from the start i.e. the first time it is opened so as not to seem buggy.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.input.MouseEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.collections.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Side;
public class bugdemo extends Application {
// Elements needed in both threads
RadioButton radioBoxersOne = new RadioButton("One");
RadioButton radioBoxersTwo = new RadioButton("Two");
TextField warmupText = new TextField("skip warm up");
TextField noCyclesText = new TextField("3");
TextField cycleTimeText = new TextField("45");
TextField restingTimeText = new TextField("30");
String[] warmupTFtext = {"skip warm up", "\u00FCberspringen"};
public static void main(String... args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
// root container
AnchorPane anchor = new AnchorPane();
// Options TitledPane
GridPane trainingOptions = new GridPane();
ToggleGroup toggleGroup = new ToggleGroup();
radioBoxersOne.setToggleGroup(toggleGroup);
radioBoxersTwo.setToggleGroup(toggleGroup);
radioBoxersOne.setSelected(true);
HBox hbToggle = new HBox(15, radioBoxersOne, radioBoxersTwo);
hbToggle.setPadding(new Insets(5,0,0,0));
ObservableList<String> langList = FXCollections.observableArrayList("English", "Deutsch");
ChoiceBox<String> langBox = new ChoiceBox<String>(langList);
langBox.setValue("English");
HBox hbLangBox = new HBox(0, langBox);
hbLangBox.setPadding(new Insets(5,0,0,0));
Label warmupOptionsLabel = new Label("Warm up time (min): ");
Label noCyclesOptionsLabel = new Label("Number of cycles: ");
Label cycleOptionsLabel = new Label("Cycle time (sec): ");
Label restingOptionsLabel = new Label("Resting time (sec): ");
Label noBoxersOptionsLabel = new Label("Number of boxers: ");
Label langOptionsLabel = new Label("Language: ");
trainingOptions.add(warmupOptionsLabel, 0, 0);
trainingOptions.add(noCyclesOptionsLabel, 0, 1);
trainingOptions.add(cycleOptionsLabel, 0, 2);
trainingOptions.add(restingOptionsLabel, 0, 3);
trainingOptions.add(noBoxersOptionsLabel, 0, 4);
trainingOptions.add(langOptionsLabel, 0, 5);
trainingOptions.add(warmupText, 1, 0);
trainingOptions.add(noCyclesText, 1, 1);
trainingOptions.add(cycleTimeText, 1, 2);
trainingOptions.add(restingTimeText, 1, 3);
trainingOptions.add(hbToggle, 1, 4);
trainingOptions.add(hbLangBox, 1, 5);
TitledPane TPane_in = new TitledPane("Options", trainingOptions);
// Options TPane and Buttons together as UI (input)
VBox UI = new VBox(10, /* hbButtons ,*/ TPane_in);
anchor.getChildren().add(UI);
AnchorPane.setLeftAnchor(UI, 25.0);
AnchorPane.setTopAnchor(UI, 100.0);
// EventHandlers for the radio-buttons
radioBoxersOne.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
/* if (!singleBoxer){
trainingProgress.getChildren().remove(boxerLabel);
trainingProgress.getChildren().remove(boxerText);
}
changeTextFlow();
singleBoxer = true; */
}
});
radioBoxersTwo.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
/* singleBoxer = false;
trainingProgress.add(boxerLabel, 0, 3);
trainingProgress.add(boxerText, 1, 3);
changeTextFlow(); */
}
});
// "EventHandler" for the language ChoiceBox
langBox.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {
public void changed(ObservableValue ov, Number value, Number new_value) {
/* language = (int)new_value;
changeLanguage(); */
}
});
// initialize scene and show stage
Scene scene = new Scene(anchor, 800, 650);
primaryStage.setScene(scene);
primaryStage.setResizable(false); // resizeable on/off
// import CSS file
// scene.getStylesheets().add(Letsbox.class.getResource("Training.css").toExternalForm());
primaryStage.show();
langBox.show();
langBox.hide();
langBox.show();
}
}
In this example no CSS is used, but the problem persists...
I tried to fix it with:
/* langBox.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
ContextMenu cm = langBox.getContextMenu();
cm.show(cm.getOwnerNode(), Side.BOTTOM, 0.0, 0.0);
}
}); */
but it throws a NullPointerException...
Please tell me how I could fix this :)
public class Main extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group(), 450, 250);
Button notification = new Button();
notification.setPrefSize(80, 60);
notification.setAlignment(Pos.CENTER);
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item4 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item5 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item6 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item7 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item8 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
final ContextMenu contextMenu = new ContextMenu(item1, item2,item3, item4,item5, item6,item7, item8);
contextMenu.setMaxSize(50, 50);
contextMenu.setOnShowing(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("showing");
}
});
contextMenu.setOnShown(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("shown");
}
});
// contextMenu.hide();
notification.setContextMenu(contextMenu);
GridPane grid = new GridPane();
grid.setVgap(4);
grid.setHgap(10);
grid.setPadding(new Insets(5, 5, 5, 5));
grid.add(new Label("To: "), 0, 0);
grid.add(notification, 1, 0);
Group root = (Group) scene.getRoot();
root.getChildren().add(grid);
stage.setScene(scene);
stage.show();
notification.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent me)->{
if(me.getButton()==MouseButton.PRIMARY ){
System.out.println("Mouse Left Pressed");
System.out.println(notification.getScaleX());
System.out.println(notification.getScaleY());
System.out.println(me.getScreenX());
System.out.println(me.getScreenY());
contextMenu.show(notification,Side.TOP,0,0);
//contextMenu.show(notification,me.getScreenX(),me.getScreenY());
}else{
contextMenu.hide();
}
});
}
}
I have an application with checkBox and 2 animated charts: Pie and Bar charts.
When checkBox is checked, method which adds new data to a chart is fired.
When checkBox is *un*checked, method which removes data from a chart is fired.
Everything is ok when i click a checkbox not very fast. But if i'll click checkbox again before its animation is finished, i recieve this one error:
java.lang.NullPointerException
at javafx.scene.chart.PieChart$7.handle(PieChart.java:370)
at javafx.scene.chart.PieChart$7.handle(PieChart.java:367)
at com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:217)
at com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:158)
at javafx.animation.Timeline.impl_playTo(Timeline.java:182)
at com.sun.scenario.animation.shared.SingleLoopClipEnvelope.timePulse(SingleLoopClipEnvelope.java:119)
at javafx.animation.Animation.impl_timePulse(Animation.java:953)
at com.sun.scenario.animation.shared.AnimationPulseReceiver.timePulse(AnimationPulseReceiver.java:117)
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:366)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:289)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:454)
at com.sun.javafx.tk.quantum.QuantumToolkit$8.run(QuantumToolkit.java:325)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$2$1.run(WinApplication.java:62)
at java.lang.Thread.run(Unknown Source)
And this all happens only with PieChart. BarChart works normally.
Here is a method for checkBox onAction event:
public void OnCheckFired(ActionEvent event) {
Boolean b = checkBox.isSelected();
chart.modifyChart(currentChart,b);
}
Thant is a code, which is fired, for modification of pie chart:
#Override
public void makeModifications(Chart chart, Boolean b) {
PieChart pie = (PieChart) chart;
ObservableList<PieChart.Data> pieChartData = pie.getData();
pieChartData = modify(b, pieChartData);
pie.setData(pieChartData);
}
private ObservableList<Data> modify(Boolean b, ObservableList<PieChart.Data> pieChartData) {
if (b) {
pieChartData.add(new PieChart.Data("newValue", 34));
} else {
int size = pieChartData.size() - 1;
pieChartData.remove(size);
}
return pieChartData;
}
I have modified the code attached to the bug issue which is Sergey mentioned in his answer. Replaced the button with checkbox that is being disabled while the animation is playing and extra half second when the animation finished. It behaves this way every time when the selection changed.
public class Tdesst extends Application {
private void init(Stage primaryStage) {
VBox root = new VBox();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
final ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
new PieChart.Data("Sun", 20),
new PieChart.Data("IBM", 12),
new PieChart.Data("HP", 25),
new PieChart.Data("Dell", 22),
new PieChart.Data("Apple", 30));
final PieChart chart = new PieChart(pieChartData);
final CheckBox chkbox = new CheckBox("add/remove data");
final Timeline animation = new Timeline(
new KeyFrame(Duration.seconds(.5),
new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
chkbox.setDisable(false);
}
}));
animation.setCycleCount(1);
chkbox.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldVal, Boolean newVal) {
chkbox.setDisable(true);
if (newVal) {
pieChartData.add(new PieChart.Data("newValue", 34));
} else {
pieChartData.remove(pieChartData.size() - 1);
}
animation.play();
}
});
root.getChildren().add(chart);
root.getChildren().add(chkbox);
}
#Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
primaryStage.setTitle(VersionInfo.getRuntimeVersion());
}
public static void main(String[] args) {
launch(args);
}
}
Or you can totally disable animating by
chart.setAnimated(false);
Unfortunately you found a bug. I've filed it as http://javafx-jira.kenai.com/browse/RT-21783
Meanwhile as a workaround you can disable checkbox for a second after each click.