What i need to do?
I need to display a lot of Data.
1 GridPane exists of ~25 Labels. There need to be 100-500 of those GridPanes to be shown.
How did i do it?
I used a ScrollPane for it.
So there are many GridPanes in a VBox which is placed into a ScrollPane.
I generate the GridPanes in an extra Thread and just set the Content of the ScrollPane in the JavaFX-Thread.
Some of those Labels are modified Labels so they are copyable or Links.
What happens?
The UI freezes for some seconds bevor the data is displayed.
Question1: Is there some modification i can make to prevent the UI from freezing?
Question2: Are there other Components better suited to display such Data?
ExampleCode:
package samples.longload;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Longload extends Application
{
private final Button runButton = new Button("Run");
private final Label label = new Label();
final ScrollPane sp = new ScrollPane();
final VBox vb = new VBox();
private final Service service = new Service()
{
#Override
protected Task createTask()
{
return new Task<Void>()
{
#Override
protected Void call() throws Exception
{
final List<Node> nodeList = new ArrayList<Node>();
for (int i = 0; i < 500; i++)
{
final GridPane grid = defineGrid();
nodeList.add(grid);
}
vb.getChildren().addAll(nodeList);
Platform.runLater(new Runnable()
{
#Override
public void run()
{
sp.setContent(vb);
}
});
return null;
}
};
}
};
#Override
public void start(final Stage stage)
{
final VBox layout = createLayout();
final Scene scene = new Scene(layout, 1500, 1000);
stage.setScene(scene);
bindUIandService(stage);
stage.show();
}
private void bindUIandService(final Stage stage)
{
label.textProperty()
.bind(service.stateProperty().asString()
);
stage.getScene()
.getRoot()
.cursorProperty()
.bind(
Bindings
.when(service.runningProperty())
.then(Cursor.WAIT)
.otherwise(Cursor.DEFAULT)
);
runButton
.disableProperty()
.bind(
service.runningProperty()
);
runButton.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(final ActionEvent event)
{
service.restart();
}
});
}
private VBox createLayout()
{
final VBox layout = new VBox(10);
sp.setPrefSize(300, 500);
sp.setVmax(440);
sp.setContent(new ProgressIndicator());
layout.getChildren().setAll(runButton, label, sp);
layout.setPadding(new Insets(10));
layout.setAlignment(Pos.CENTER);
return layout;
}
public static void main(final String[] args)
{
launch(args);
}
private LinkedHashMap<Node, Node> createContentMap()
{
final LinkedHashMap<Node, Node> contentMap = new LinkedHashMap<Node, Node>();
// ID-KONSEH
contentMap.put(new Label("1"), new Label("1", null));
// ID-DOKUMENT
contentMap.put(new Label("2"), new Label("2"));
// DISCRIMINATOR
contentMap.put(new Label("3"), new Label("3"));
// AKT
contentMap.put(new Label("4"), new Label("4"));
// FASSUNGSNR
contentMap.put(new Label("5"), new Label("5"));
// KORREKTURNR
contentMap.put(new Label("6"), new Label("6"));
// STATUS
contentMap.put(new Label("7"), new Label("7"));
// NEUZUGANG
contentMap.put(new Label("8"), new Label("8"));
// NEUZDAT
contentMap.put(new Label("9"), new Label("9"));
// APPDATVON
contentMap.put(new Label("10"), new Label("10"));
// APPDATBIS
contentMap.put(new Label("11"), new Label("11"));
// BEZUGVON
contentMap.put(new Label("12"), new Label("12"));
// BEZUGBIS
contentMap.put(new Label("13"), new Label("13"));
// INKRAFTVON
contentMap.put(new Label("14"), new Label("14"));
// INKRAFTBIS
contentMap.put(new Label("15"), new Label("15"));
// APPROBANT
contentMap.put(new Label("16"), new Label("16"));
// SACHBEARBEITER
contentMap.put(new Label("17"), new Label("17"));
// KURZTEXT
contentMap.put(new Label("18"), new Label("18"));
// PERSANMERKUNG
contentMap.put(new Label("19"), new Label("19"));
// LASTCHANGEDAT
contentMap.put(new Label("20"), new Label("20"));
// WIEDERVORLAGE_DATUM
contentMap.put(new Label("21"), new Label("21"));
// TEMP_GID
contentMap.put(new Label("22"), new Label("22"));
// DOK_MULTIFASSUNG
contentMap.put(new Label("23"), new Label("23"));
// ABGEFERTIGT_VON
contentMap.put(new Label("24"), new Label("24"));
// KORRIGIERT_VON
contentMap.put(new Label("25"), new Label("25"));
return contentMap;
}
public GridPane defineGrid()
{
final GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10)); // top, right, bottom, left
grid.setHgap(10); // horizontaler Abstand
grid.setVgap(10); // vertikaler Abstand
final int columnWidthDescription = 150; // breite der Beschreibungs-Spalten
final int columnWidthContent = 250; // breite der Inhalts-Spalten
final ColumnConstraints columnDescription1 = new ColumnConstraints(columnWidthDescription, columnWidthDescription, columnWidthDescription);
final ColumnConstraints columnContent1 = new ColumnConstraints(columnWidthContent, columnWidthContent, columnWidthContent);
final ColumnConstraints columnDescription2 = new ColumnConstraints(columnWidthDescription, columnWidthDescription, columnWidthDescription);
final ColumnConstraints columnContent2 = new ColumnConstraints(columnWidthContent, columnWidthContent, columnWidthContent);
final ColumnConstraints columnDescription3 = new ColumnConstraints(columnWidthDescription, columnWidthDescription, columnWidthDescription);
final ColumnConstraints columnContent3 = new ColumnConstraints(columnWidthContent, columnWidthContent, columnWidthContent);
grid.getColumnConstraints().addAll(columnDescription1, columnContent1, columnDescription2, columnContent2, columnDescription3,
columnContent3);
final LinkedHashMap<Node, Node> contentMap = createContentMap();
int column = 0;
int row = 1;
for (final Node desc : contentMap.keySet())
{
final Node content = contentMap.get(desc);
if (row > contentMap.size() / 3)
{
column = column + 2;
row = 1;
}
grid.add(desc, column, row);
grid.add(content, column + 1, row);
row++;
}
return grid;
}
}
This is how it should look like in the end:
Related
I'm trying to implement an EventHandler for a "store" type application that will allow the user to add or remove items from a cart, then display the remaining balance of a user-entered budget on the side. However, I am having issues with how to handle this. My professor told me to use the getSource() method but I'm unsure of how to implement that here in my code for what I specifically need it to do. My professor also told me I could use an Array List for the buttons but I'm awful at Array List's so if there's a way around that, that would be great.
`
import javafx.application.Application;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Label;
import javafx.geometry.Insets;
import java.util.Scanner;
public class ShoppingCart extends Application {
Image shirt = new Image("file:shirt.jpg");
Image jacket = new Image("file:jacket.jpg");
Image pants = new Image("file:pants.jpg");
Image shorts = new Image("file:shorts.jpg");
Image shoes = new Image("file:shoes.jpg");
Image socks = new Image("file:socks.jpg");
Image hat = new Image("file:hat.jpg");
Image gloves = new Image("file:gloves.jpg");
ImageView shirtView = new ImageView(shirt);
ImageView jacketView = new ImageView(jacket);
ImageView pantsView = new ImageView(pants);
ImageView shortsView = new ImageView(shorts);
ImageView shoesView = new ImageView(shoes);
ImageView socksView = new ImageView(socks);
ImageView hatView = new ImageView(hat);
ImageView glovesView = new ImageView(gloves);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
shirtView.setPreserveRatio(true);
shirtView.setFitHeight(200);
jacketView.setPreserveRatio(true);
jacketView.setFitHeight(200);
pantsView.setPreserveRatio(true);
pantsView.setFitHeight(200);
shortsView.setPreserveRatio(true);
shortsView.setFitHeight(200);
shoesView.setPreserveRatio(true);
shoesView.setFitHeight(200);
socksView.setPreserveRatio(true);
socksView.setFitHeight(200);
hatView.setPreserveRatio(true);
hatView.setFitHeight(200);
glovesView.setPreserveRatio(true);
glovesView.setFitHeight(200);
Label shirtPrice = new Label("$12");
Label jacketPrice = new Label("$20");
Label pantsPrice = new Label("$15");
Label shortsPrice = new Label("$15");
Label shoesPrice = new Label("$30");
Label socksPrice = new Label("$5");
Label hatPrice = new Label("$10");
Label glovesPrice = new Label("$8");
int shirtCost = 12;
int jacketCost = 20;
int pantsCost = 15;
int shortsCost = 15;
int shoesCost = 30;
int socksCost = 5;
int hatCost = 10;
int glovesCost = 8;
Scanner custBudget = new Scanner(System.in);
TextField budget = new TextField("Please enter your budget...");
int scBudget = custBudget.nextInt();
Label budgetLabel = new Label();
budgetLabel.setText(String.valueOf(scBudget));
GridPane gridPane = new GridPane();
gridPane.add(shirtView, 0,0);
gridPane.add(jacketView, 0, 1);
gridPane.add(pantsView, 0, 2);
gridPane.add(shortsView, 0, 3);
gridPane.add(shoesView, 1, 0);
gridPane.add(socksView, 1, 1);
gridPane.add(hatView, 1, 2);
gridPane.add(glovesView, 1, 3);
Button addButton = new Button("Add To Cart");
addButton.setOnAction(new AddToCart());
Button removeButton = new Button("Remove From Cart");
removeButton.setOnAction(new RemoveFromCart());
HBox cartButtons = new HBox(20, addButton, removeButton);
VBox shirtItem = new VBox(shirtView, shirtPrice, cartButtons);
VBox jacketItem = new VBox(jacketView, jacketPrice, cartButtons);
VBox pantsItem = new VBox(pantsView, pantsPrice, cartButtons);
VBox shortsItem = new VBox(shortsView, shortsPrice, cartButtons);
VBox shoesItem = new VBox(shoesView, shoesPrice, cartButtons);
VBox socksItem = new VBox(socksView, socksPrice, cartButtons);
VBox hatItem = new VBox(hatView, hatPrice, cartButtons);
VBox glovesItem = new VBox(glovesView, glovesPrice, cartButtons);
HBox row1 = new HBox(20, shirtItem, jacketItem, pantsItem, shortsItem, budgetLabel);
HBox row2 = new HBox(20, shoesItem, socksItem, hatItem, glovesItem);
VBox rows = new VBox(20, row1, row2, budget);
gridPane.setAlignment(Pos.CENTER);
gridPane.setHgap(20);
gridPane.setVgap(20);
gridPane.setPadding(new Insets(10,10,10,10));
Scene scene = new Scene(gridPane, 1200, 800);
primaryStage.setScene(scene);
primaryStage.setTitle("Clothes Shopping");
primaryStage.show();
}
public class AddToCart implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
if (event.getSource() == addButton) {
}
}
}
public class RemoveFromCart implements EventHandler<ActionEvent> {
#Override
public void handle(ActionEvent event) {
}
}
}
`
I found this code in a thread and basically I want to change it so when I click on the treeView node 'High' I want the right pane to display a tabPane (instead of label and textfield) and inside the tabPane I want to display a TableView. I've attached a pic of what the GUI does. Any help would be appreciated, thanks.
Attached what the GUI does: to get to 'High' right click component A and select 'Add Parameter'
GUI example
Main.java
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.util.HashMap;
import java.util.Map;
public class Main extends Application {
private static int rootNr = 0;
private static int coordinateNr = 0;
public static void main(String[] args) {
launch(args);
}
static final Map<TreeItem<String>, BorderPane> map = new HashMap<>();
TabPane tabPane;
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
TreeItem<String> tree = new TreeItem<>("Project");
TreeItem<String> item1 = new TreeItem<>("Component A");
TreeView<String> treeView = new TreeView<>(tree);
treeView.setOnMouseClicked((event) -> {
TreeItem<String> treeItem = treeView.getSelectionModel().getSelectedItem();
if (treeItem.getChildren().stream().anyMatch(child -> child.getValue().startsWith("C"))) {
root.setCenter(getRootsPanel(treeItem.getValue()));
} else {
root.setCenter(map.get(treeItem));
}
});
treeView.setCellFactory(p -> new AddMenuTreeCell());
tree.setExpanded(true);
root.setLeft(treeView);
tree.getChildren().add(item1);
Scene scene = new Scene(root, 700, 500);
primaryStage.setTitle("Tree View");
primaryStage.setScene(scene);
primaryStage.show();
}
private static class AddMenuTreeCell extends TextFieldTreeCell<String> {
private ContextMenu menu = new ContextMenu();
public AddMenuTreeCell() {
MenuItem newitem1 = new MenuItem("Add Component");
MenuItem newitem2 = new MenuItem("Add Parameter");
menu.getItems().addAll(newitem1, newitem2);
newitem1.setOnAction(arg0 -> {
TreeItem<String> item3 = new TreeItem<>("Component X");
getTreeItem().getChildren().add(item3);
});
newitem2.setOnAction(arg0 -> {
TreeItem<String> newLeaf = new TreeItem<>("Parameter");
TreeItem<String> uxItem1 = new TreeItem<>("High");
map.put(uxItem1, getrightPane1());
TreeItem<String> uyItem1 = new TreeItem<>("Low");
map.put(uyItem1, getrightPane1());
newLeaf.getChildren().add(uxItem1);
newLeaf.getChildren().add(uyItem1);
getTreeItem().getChildren().add(newLeaf);
});
}
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (!isEditing()) {
setText(item);
setGraphic(getTreeItem().getGraphic());
if (!(getTreeItem().isLeaf() && getTreeItem().getParent() == null)) {
setContextMenu(menu);
}
}
}
}
}
private static BorderPane getrightPane1() {
TextField textf1 = new TextField();
TextField textf2 = new TextField();
BorderPane root1 = new BorderPane();
VBox vbox = new VBox(20);
vbox.setPadding(new Insets(10));
HBox h1 = new HBox(7);
HBox h2 = new HBox(7);
textf1.setPrefWidth(100);
textf1.setPromptText("Enter Height");
textf1.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect1 = new Rectangle();
rect1.setHeight(Double.parseDouble(textf1.getText()));
rect1.setWidth(Double.parseDouble(textf2.getText()));
rect1.setFill(null);
rect1.setStroke(Color.RED);
root1.setCenter(rect1);
}
});
textf2.setPrefWidth(100);
textf2.setPromptText("Enter Width");
textf2.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect2 = new Rectangle();
rect2.setHeight(Double.parseDouble(textf1.getText()));
rect2.setWidth(Double.parseDouble(textf2.getText()));
rect2.setFill(null);
rect2.setStroke(Color.RED);
root1.setCenter(rect2);
}
});
if (textf1.getText().length() > 0 && textf2.getText().length() > 0 && root1.getCenter() == null) {
Rectangle rect = new Rectangle();
rect.setHeight(Double.parseDouble(textf1.getText()));
rect.setWidth(Double.parseDouble(textf2.getText()));
rect.setFill(null);
rect.setStroke(Color.RED);
root1.setCenter(rect);
}
h1.getChildren().addAll(new Label("Y1:"), textf1);
h2.getChildren().addAll(new Label("X1:"), textf2);
vbox.getChildren().addAll(h1, h2);
root1.setLeft(vbox);
return root1;
}
private static BorderPane getRootsPanel(String root) {
BorderPane root2 = new BorderPane();
HBox hbox = new HBox(10);
hbox.setPadding(new Insets(40));
hbox.setAlignment(Pos.TOP_CENTER);
for (Map.Entry<TreeItem<String>, BorderPane> entry : map.entrySet()) {
if (entry.getKey().getParent().getParent().getValue().equals(root)) {
Rectangle rect1 = (Rectangle) entry.getValue().getCenter();
if (rect1 != null) {
Rectangle rect2 = new Rectangle();
rect2.setWidth(rect1.getWidth());
rect2.setHeight(rect1.getHeight());
rect2.setFill(rect1.getFill());
rect2.setStroke(rect1.getStroke());
Platform.runLater(() -> hbox.getChildren().add(rect2));
}
}
}
Platform.runLater(() -> root2.setLeft(hbox));
return root2;
}
}
I am tasked with creating a DVD Collection application that displays Three columns and five row of stuff. I have written the code for this to work but keep on getting compilation errors( CANNOT FIND SYMBOL ==> class DVDColletionApp ) that I am having a hard time debugging.
Below is the code in question. Assistance would be greatly appreciated.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
public class DVDCollectionApp extends Application {
private DVDCollection model;
private ListView<String> tList;
private ListView<Integer> yList, lList;
public DVDCollectionApp() {
model = DVDCollection.example1();
}
public void start(Stage primaryStage) {
BorderPane borderPane = new BorderPane();
// Create the labels
HBox labelPane = new HBox();
labelPane.setPadding(new Insets(0,0,0,10));
labelPane.setSpacing(10);
Label label1 = new Label("Title");
label1.setMinSize(300,30);
label1.setPrefSize(2000,30);
Label label2 = new Label("Year");
label2.setMinSize(60,30);
label2.setPrefSize(60,30);
Label label3 = new Label("Length");
label3.setMinSize(60,30);
label3.setPrefSize(60,30);
labelPane.getChildren().addAll(label1, label2, label3);
borderPane.setTop(labelPane);
// Create the lists
GridPane listPane = new GridPane();
listPane.setPadding(new Insets(10));
listPane.setHgap(10);
tList = new ListView<String>();
listPane.add(tList, 0, 0);
tList.setMinSize(300,60);
tList.setPrefSize(2000,2000);
yList = new ListView<Integer>();
listPane.add(yList, 1, 0);
yList.setMinSize(60,60);
yList.setPrefSize(60,500);
lList = new ListView<Integer>();
listPane.add(lList, 2, 0);
lList.setMinSize(60,60);
lList.setPrefSize(60,500);
borderPane.setCenter(listPane);
// Create the button pane
HBox buttonPane = new HBox();
buttonPane.setPadding(new Insets(10));
buttonPane.setSpacing(10);
Button addButton = new Button("Add");
addButton.setStyle("-fx-font: 12 arial; -fx-base: rgb(0,100,0); -fx-text-fill: rgb(255,255,255);");
addButton.setPrefSize(90,30);
Button deleteButton = new Button("Delete");
deleteButton.setStyle("-fx-font: 12 arial; -fx-base: rgb(200,0,0); -fx-text-fill: rgb(255,255,255);");
deleteButton.setPrefSize(90,30);
Button statsButton = new Button("Stats");
statsButton.setStyle("-fx-font: 12 arial;");
statsButton.setPrefSize(90,30);
buttonPane.getChildren().addAll(addButton, deleteButton, statsButton);
borderPane.setBottom(buttonPane);
addButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent actionEvent) {
String title = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Title: ");
String year = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Year: ");
String length = javax.swing.JOptionPane.showInputDialog("Please enter the DVD Duration: ");
if ((title != null) && (year != null) && (length != null) && (title.length() > 0) && (year.length() > 0) && (length.length() > 0)) {
DVD d = new DVD(title, Integer.parseInt(year), Integer.parseInt(length));
model.add(d);
update(model, -1);
}
}
});
deleteButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent actionEvent) {
if (tList.getSelectionModel().getSelectedItem() != null) {
model.remove(tList.getSelectionModel().getSelectedItem());
update(model, -1);
}
}
});
tList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(tList.getSelectionModel().getSelectedIndex());
update(model, tList.getSelectionModel().getSelectedIndex());
}
});
yList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(yList.getSelectionModel().getSelectedIndex());
update(model, yList.getSelectionModel().getSelectedIndex());
}
});
lList.setOnMousePressed(new EventHandler<MouseEvent>() {
public void handle(MouseEvent mouseEvent) {
model.setSelectedDVD(lList.getSelectionModel().getSelectedIndex());
update(model, lList.getSelectionModel().getSelectedIndex());
}
});
// Populate the lists
DVD[] theList = model.getDVDList();
String[] titles = new String[theList.length];
Integer[] years = new Integer[theList.length];
Integer[] lengths = new Integer[theList.length];
for (int i=0; i<theList.length; i++) {
titles[i] = theList[i].getTitle();
years[i] = theList[i].getYear();
lengths[i] = theList[i].getDuration();
}
tList.setItems(FXCollections.observableArrayList(titles));
yList.setItems(FXCollections.observableArrayList(years));
lList.setItems(FXCollections.observableArrayList(lengths));
primaryStage.setTitle("My DVD Collection");
primaryStage.setScene(new Scene(borderPane, 600, 300));
primaryStage.show();
}
// Update the view to reflect the model
public void update(DVDCollection model, int selectedDVD) {
DVD[] theList = model.getDVDList();
String[] titles = new String[theList.length];
Integer[] years = new Integer[theList.length];
Integer[] lengths = new Integer[theList.length];
for (int i=0; i<theList.length; i++) {
titles[i] = theList[i].getTitle();
years[i] = theList[i].getYear();
lengths[i] = theList[i].getDuration();
}
tList.setItems(FXCollections.observableArrayList(titles));
yList.setItems(FXCollections.observableArrayList(years));
lList.setItems(FXCollections.observableArrayList(lengths));
tList.getSelectionModel().select(selectedDVD);
yList.getSelectionModel().select(selectedDVD);
lList.getSelectionModel().select(selectedDVD);
}
public static void main(String[] args) {
launch(args);
}
}
Have you checked that java files are being compiled correctly?
The class DVDCollection doesn't seem to be imported, the DVDCollectionApp class must be in a .java of the same name and if you're using an IDE be sure to do a clean&build.
I want to change the text under Progress Indicator. By default, when the ProgressIndicator has completed its Progress the text is Done, I want to be able to edit this text with any user-defined text or text depending on the locale.
When I run the program output shows that text has been changed, but on the GUI it doesn't change. Please look at the following pictures :
MCVE
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
Task copyWorker;
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Background Processes");
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
BorderPane mainPane = new BorderPane();
root.getChildren().add(mainPane);
final Label label = new Label("Files Transfer:");
final ProgressIndicator progressIndicator = new ProgressIndicator(0);
progressIndicator.progressProperty().addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> ov, Number t, Number newValue) {
progressIndicator .applyCss();
// If progress is 100% then show Text
if (newValue.doubleValue() >= 1.0) {
// Apply CSS so you can lookup the text
Text text = (Text) progressIndicator .lookup(".percentage");//also I checked .lookup(.text.percentage) version
System.out.println(text.getText());
// This text replaces "Done"
text.setText("some text");
//for testing
Text x= (Text) progressIndicator .lookup(".percentage");
System.out.println(x.getText());//output shows that the text under progress indicator is changed
}
}});
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressIndicator);
mainPane.setTop(hb);
final Button startButton = new Button("Start");
final Button cancelButton = new Button("Cancel");
final HBox hb2 = new HBox();
hb2.setSpacing(5);
hb2.setAlignment(Pos.CENTER);
hb2.getChildren().addAll(startButton, cancelButton);
mainPane.setBottom(hb2);
startButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(true);
progressIndicator.setProgress(0);
cancelButton.setDisable(false);
copyWorker = createWorker();
progressIndicator.progressProperty().unbind();
progressIndicator.progressProperty().bind(copyWorker.progressProperty());
copyWorker.messageProperty().addListener(new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.println(newValue);
}
});
new Thread(copyWorker).start();
}
});
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
startButton.setDisable(false);
cancelButton.setDisable(true);
copyWorker.cancel(true);
progressIndicator.progressProperty().unbind();
progressIndicator.setProgress(0);
System.out.println("cancelled.");
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
public Task createWorker() {
return new Task() {
#Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
updateMessage("100 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
}
You need to change the text of the ProgressIndicator as well as set the width of the ProgressIndicator to the new width of the Text.
progressIndicator.progressProperty().addListener((ov, oldValue, newValue) -> {
Text text = (Text) progressIndicator.lookup(".percentage");
if(text!=null && text.getText().equals("Done")){
text.setText("New Text");
progressIndicator.setPrefWidth(text.getLayoutBounds().getWidth());
}
});
Complete Code
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
Task copyWorker;
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Background Processes");
Group root = new Group();
Scene scene = new Scene(root, 330, 120, Color.WHITE);
BorderPane mainPane = new BorderPane();
root.getChildren().add(mainPane);
final Label label = new Label("Files Transfer:");
final ProgressIndicator progressIndicator = new ProgressIndicator(0);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(label, progressIndicator);
mainPane.setTop(hb);
final Button startButton = new Button("Start");
final Button cancelButton = new Button("Cancel");
final HBox hb2 = new HBox();
hb2.setSpacing(5);
hb2.setAlignment(Pos.CENTER);
hb2.getChildren().addAll(startButton, cancelButton);
mainPane.setBottom(hb2);
startButton.setOnAction(event -> {
startButton.setDisable(true);
progressIndicator.setProgress(0);
cancelButton.setDisable(false);
copyWorker = createWorker();
progressIndicator.progressProperty().unbind();
progressIndicator.progressProperty().bind(copyWorker.progressProperty());
new Thread(copyWorker).start();
});
cancelButton.setOnAction(event -> {
startButton.setDisable(false);
cancelButton.setDisable(true);
copyWorker.cancel(true);
progressIndicator.progressProperty().unbind();
progressIndicator.setProgress(0);
});
primaryStage.setScene(scene);
primaryStage.show();
progressIndicator.progressProperty().addListener((observable, oldValue, newValue) -> {
Text text = (Text) progressIndicator.lookup(".percentage");
if (text != null && text.getText().equals("Done")) {
text.setText("New Text");
progressIndicator.setPrefWidth(text.getLayoutBounds().getWidth());
}
});
}
public Task createWorker() {
return new Task() {
#Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(500);
updateMessage("2000 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
public static void main(String[] args) {
Application.launch(args);
}
}
It's posiible to change ProgressIndicator label (and all other default labels, like TextField context menu labels) by overwrite controls bundle file. In this file you have field:
ProgressIndicator.doneString=YourTextHere
How to overwrite ResourceBundle file you'll find here:
https://stackoverflow.com/a/48773353/7746751
Why these statements does not work?
if (iv_ship.intersects(iv_plane.getBoundsInLocal())) System.out.println("xxxxxxxxx");
if (iv_plane.intersects(iv_ship.getBoundsInLocal())) System.out.println("zzzz");
if (iv_plane.getBoundsInLocal().intersects(iv_ship.getBoundsInLocal())) System.out.println("dupa");
I am pretty sure these two objects intersect. Maybe it is fault of TranslateTransition?
But i was also trying to intersect Rectangles in coast, which are not TT.
Best regards.
Here is all the code:
package riverpuff.v3;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* #author Marek
*/
public class RiverPuffV3 extends Application {
public String name = "";
public Rectangle shot = new Rectangle();
#Override
public void start(Stage primaryStage) {
createMenu(primaryStage);
primaryStage.show();
primaryStage.setResizable(false);
primaryStage.getIcons().
add(new Image(getClass().getResourceAsStream("Icon.png")));
}
private void createMenu(Stage primaryStage) {
primaryStage.setScene(null);
GridPane pane_menu = new GridPane();
Button button_name = new Button("Name");
button_name.setMaxHeight(Double.MAX_VALUE);
button_name.setMaxWidth(Double.MAX_VALUE);
button_name.setOnAction(e -> {
createName(primaryStage);
/*try{
OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream("log.txt", true), "UTF-8");
BufferedWriter fbw = new BufferedWriter(writer);
fbw.newLine();
fbw.write("append txt...");
fbw.newLine();
fbw.close();
}
catch (Exception v) {
System.out.println("Error: " + v.getMessage());
}*/
});
Button button_start = new Button("Start");
button_start.setMaxHeight(Double.MAX_VALUE);
button_start.setMaxWidth(Double.MAX_VALUE);
button_start.setOnAction(e -> {
drawGame(primaryStage);
});
pane_menu.setHgap(10);
pane_menu.setVgap(10);
pane_menu.add(button_name,0,10,10,10);
pane_menu.add(button_start,15,10,10,10);
//reading name from a file
try {
String read_file = null;
BufferedReader in = new BufferedReader(new FileReader("log.txt"));
read_file = in.readLine();
Text text_name = new Text("Hello " + read_file);
pane_menu.add(text_name,5,5,10,5);
} catch (FileNotFoundException e) {
System.out.println("File not found!");
//throw new RuntimeException("File not found");
} catch (IOException e) {
System.out.println("IO Error occured");
//throw new RuntimeException("IO Error occured");
}
Scene scene_menu = new Scene(pane_menu, 300, 500);
primaryStage.setTitle("River Puff");
primaryStage.setScene(scene_menu);
}
//save name to a file
private void createName (Stage primaryStage) {
primaryStage.setScene(null);
GridPane pane_name = new GridPane();
TextField tf_name = new TextField();
tf_name.setMaxHeight(50);
tf_name.setMaxWidth(240);
tf_name.setAlignment(Pos.CENTER);
tf_name.setFont(Font.font("Verdana",25));
tf_name.setOnKeyPressed(ke -> {
if (ke.getCode() == KeyCode.ENTER) {
name = tf_name.getText();
if (!name.isEmpty()){
MyFile myFile = new MyFile();
myFile.writeTextFile("log.txt", name);
}
createMenu(primaryStage);
}
});
Button button_ok = new Button("OK");
button_ok.setMaxHeight(30);
button_ok.setMaxWidth(80);
button_ok.setOnAction(e -> {
name = tf_name.getText();
if (!name.isEmpty()){
MyFile myFile = new MyFile();
myFile.writeTextFile("log.txt", name);
}
createMenu(primaryStage);
});
Text text_name = new Text("What is your name?");
text_name.setFont(Font.font("Verdana",15));
pane_name.setHgap(10);
pane_name.setVgap(10);
pane_name.add(text_name,8,9,5,5);
pane_name.add(button_ok,11,22,8,3);
pane_name.add(tf_name,3,15,24,5);
Scene scene_name = new Scene(pane_name, 300, 500);
primaryStage.setTitle("River Puff - Name");
primaryStage.setScene(scene_name);
}
private void drawGame (Stage primaryStage) {
primaryStage.setScene(null);
final int H = 700;
final int W = 1000;
Group root = new Group();
Scene scene_game = new Scene(root, W, H, Color.LIGHTBLUE);
Button button_menu = new Button("Menu");
button_menu.setOnAction(e ->{
createMenu(primaryStage);
});
Image ship = new Image((getClass().getResourceAsStream("ship.png"))); //loading images
Image plane = new Image((getClass().getResourceAsStream("Icon.png")));
/**********************************************************************/
Rectangle[] coastL = {
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle()
};
Rectangle[] coastR = {
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle(),
new Rectangle(), new Rectangle()
};
for (int i=0; i<8; i++) {
coastL[i].setFill(Color.FORESTGREEN);
coastL[i].setHeight(100);
coastR[i].setFill(Color.FORESTGREEN);
coastR[i].setHeight(100);
}
AnimationTimer timer = new AnimationTimer() {
int[] j = {0,0,0,0,0,0,0,0};
#Override
public void handle(long now) {
for (int i=0; i<8; i++) if (j[i]==(i*100+800)) j[i]=i*100;
for (int i=1;i<9;i++) { //creating coast
coastL[i-1].setX(0);
coastL[i-1].setY(j[i-1]-(i*100));
coastL[i-1].setWidth(250+i*(i%3));
coastR[i-1].setX(W-(250+i*(i%4)));
coastR[i-1].setY(j[i-1]-(i*100));
coastR[i-1].setWidth(250+i*(i%4));
}
for (int i=0;i<8;i++) j[i]++;
}
};
timer.start();
ImageView iv_ship = new ImageView();
iv_ship.setImage(ship);
iv_ship.setFitWidth(150);
iv_ship.setFitHeight(45);
iv_ship.setX(300);
iv_ship.setY(0);
TranslateTransition tt_shipX =
new TranslateTransition(Duration.millis(2000), iv_ship); //moving enemies
tt_shipX.setAutoReverse(true);
tt_shipX.setCycleCount(Timeline.INDEFINITE);
tt_shipX.setByX(200f);
tt_shipX.play();
TranslateTransition tt_shipY =
new TranslateTransition(Duration.millis(13000), iv_ship);
tt_shipY.setAutoReverse(false);
tt_shipY.setCycleCount(Timeline.INDEFINITE);
tt_shipY.setByY(800);
tt_shipY.play();
ImageView iv_plane = new ImageView();
iv_plane.setImage(plane);
iv_plane.setFitWidth(50);
iv_plane.setFitHeight(50);
iv_plane.setX(475);
iv_plane.setY(600);
TranslateTransition tt_plane =
new TranslateTransition(Duration.millis(1), iv_plane);
TranslateTransition tt_shot =
new TranslateTransition(Duration.millis(4000), shot);
tt_shot.setAutoReverse(false);
tt_shot.setCycleCount(1);
TranslateTransition tt_shotB =
new TranslateTransition(Duration.millis(0.5f), shot);
tt_shotB.setAutoReverse(false);
tt_shotB.setCycleCount(1);
root.setOnKeyPressed((KeyEvent ke) -> { //steering a plane }
if (ke.getCode() == KeyCode.LEFT &&
tt_plane.getNode().getTranslateX() > -475) {
tt_plane.setByX(-5f);
tt_plane.play();
System.out.println(tt_plane.getNode().getTranslateX());
}
else if (ke.getCode() == KeyCode.RIGHT &&
tt_plane.getNode().getTranslateX() < 475) {
tt_plane.setByX(5f);
tt_plane.play();
System.out.println(tt_plane.getNode().getTranslateX());
}
else if (ke.getCode() == KeyCode.A) {
shot.setFill(Color.BLACK);
shot.setX(tt_plane.getNode().getTranslateX()+495);
shot.setY(580);
shot.setWidth(10);
shot.setHeight(20);
tt_shot.setByY(-600);
tt_shot.play();
tt_shot.setOnFinished((ActionEvent arg0) -> {
shot.setDisable(true);
tt_shotB.setByY(600);
tt_shotB.play();
});
}
});
if (iv_ship.intersects(iv_plane.getBoundsInLocal())) System.out.println("xxxxxxxxx");
if (iv_plane.intersects(iv_ship.getBoundsInLocal())) System.out.println("zzzz");
if (iv_plane.getBoundsInLocal().intersects(iv_ship.getBoundsInLocal())) System.out.println("dupa");
root.getChildren().add(button_menu);
for (int i=0; i<8; i++) {
root.getChildren().add(coastL[i]);
root.getChildren().add(coastR[i]);
}
root.getChildren().add(iv_plane);
root.getChildren().add(iv_ship);
root.getChildren().add(shot);
primaryStage.setScene(scene_game);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
First of all, you need to take into account that the nodes can be transformed (with translations), so instead of getBoundsInLocal() you need getBoundsInParent().
According to javadocs:
getBoundsInParent() gets the value of the property boundsInParent. The rectangular bounds of this Node which include its transforms. boundsInParent is calculated by taking the local bounds (defined by boundsInLocal) and applying the transform created.
This will work, at any given position of both nodes:
if(iv_plane.getBoundsInParent().intersects(iv_ship.getBoundsInParent())){
System.out.println("Intersection detected");
}
The next problem you have to solve is when do you check a possible intersection. Based on your code, you checked only once, when the nodes where not even added to the root/scene/stage. That couldn't work.
For this to work, you have to check everytime one of them is moved, using some listeners to changes in the translateXProperty() and translateYProperty(), something like this:
private final ChangeListener<Number> checkIntersection = (ob,n,n1)->{
if (iv_plane.getBoundsInParent().intersects(iv_ship.getBoundsInParent())){
System.out.println("Intersection detected");
}
};
private ImageView iv_ship, iv_plane;
private void drawGame (Stage primaryStage) {
iv_ship = new ImageView();
iv_plane = new ImageView();
...
iv_ship.translateXProperty().addListener(checkIntersection);
iv_ship.translateYProperty().addListener(checkIntersection);
...
root.getChildren().addAll(iv_plane,iv_ship);
primaryStage.setScene(scene_game);
}