Sort ObservableList from high to low - javafx - javafx

Is there any way to sort a ObservableList based on the values from high to low?
Say I have a
ObservableList<XYChart.Data> data;
containing a String and a Double. I want the list sorted based on the Double from highest to lowest values. The reason I want this is because charts look way better if their values are shown from the highest to the lowest.
I have something like this now:
sortedData = new SortedList<>(data);
sortedData.comparatorProperty().bind(mycomparatorProperty());

You can create a Comparator, compare by the Y value, and then reverse the order:
data.sort(Comparator.comparing(XYChart.Data<String,Double>::getYValue).reversed());
This will sort your collection as intented.
Or you can return a new collection:
List<XYChart.Data<String,Double>> sortedData =
data.stream()
.sorted(Comparator.comparing(XYChart.Data<String,Double>::getYValue).reversed())
.collect(Collectors.toList());
EDIT
For the sake of clarity, this is a full sample:
public class FXMain extends Application {
private final ObservableList<XYChart.Data<String,Double>> data =
FXCollections.observableArrayList(
new XYChart.Data("P1",200d),
new XYChart.Data("P2",150d),
new XYChart.Data("P3",250d));
#Override
public void start(Stage primaryStage) {
Button btn = new Button"Sort data!");
btn.setOnAction(e -> {
ObservableList<XYChart.Data<String,Double>> data2 =
data.stream()
.sorted(Comparator.
comparing(XYChart.Data<String,Double>::getYValue).reversed())
.peek(System.out::println)
.collect(Collectors.toCollection(()->FXCollections.observableArrayList()));
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Related

Events for two overlay shapes

My problem:
I have a two overlay shapes, for example, two rectangles: A and B.
When B overlay A rectangle.
I add setOnMouseMoved handlers for both and i see that events handles only by top figure.
Code example:
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
b.setOnMouseMoved(mouseEvent -> {
System.out.println("Mouse moved b!");
});
a.setOnMouseMoved(mouseEvent -> System.out.println("Mouse moved a!"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
What i want:
In the area of overlapping figures mouse moved events handles both of figures: A and B.
Thanx everyone for help!
I replace both mouse events to just one in stackpane node . The event checks if mouse coords is inside in both bounds (node a and node b) . When the mouse is in an area that intersetcs both rectangles the event wil thrigger both print statments
public class MainExample extends Application {
#Override
public void start(Stage stage) {
stage.setMinWidth(700);
stage.setMaxWidth(700);
stage.setMinHeight(800);
stage.setMaxHeight(800);
StackPane root = new StackPane();
var a = new Rectangle(300, 300, Color.BLUE);
var b = new Rectangle(200, 200);
root.getChildren().addAll(a, b);
root.setOnMouseMoved(mouseEvent -> {
if(b.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved b!");}
if(a.getBoundsInParent().contains(mouseEvent.getSceneX(),mouseEvent.getSceneY())){
System.out.println("Mouse moved a!");}
});
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}

Javafx TilePane PrefColumns

I am having problems producing the correct number of columns in a TilePane row.
I'm trying just to have ten columns per row. I know I'm missing the obvious. So, I need another pair of eyes.
The setPrefColumns method does not appear to work the way I have it coded.
#SuppressWarnings("unused")
public class Main extends Application {
TilePane tp = new TilePane();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
try {
primaryStage.setResizable(false);
tp.setPrefColumns(10);
setTP();
Scene scene = new Scene(tp,800,600);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public void setTP() {
tp.setVisible(true);
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
for(int row=0; row<11; row++) {
for (int i: numbers ) {
Text t = new Text(String.valueOf(i));
HBox hbox = new HBox();
hbox.getChildren().add(t);
hbox.setStyle("-fx-border-color: red;");
tp.getChildren().add(hbox);
}
}
}
}
Your example TilePane behaves as specified:
Note that prefColumns/prefRows is used only for calculating the preferred size and may not reflect the actual number of rows or columns, which may change as the tilepane is resized and the tiles are wrapped at its actual boundaries.
As root of the scene it is sized to fill the complete width (800 in your context):
Scene scene = new Scene(tp,800,600);
To make it wrap on its prefColumns, you need to add it to a layout that respects its content's prefWidth, f.i. a HBox:
Scene scene = new Scene(new HBox(tp),800,600);

Java FX - Controlling one combobox/choicebox using other combobox/choicebox

I want to change the combobox by selecting item from another combobox. Means, I want to control one combobox using other combobox. For example, if I have a combobox containing names and other containing countries, then if I select Mumbai from names then other combobox should automatically display India.
Please help me out a little bit to solve this problem. A piece of code will work for me to explain.
I think this is what you mean where the second combobox is dependent on what is chosen in the first
public class Main extends Application {
#Override
public void start(Stage stage) {
ComboBox comboBox2 = new ComboBox();
ComboBox comboBox = new ComboBox();
comboBox.getItems().addAll("Option 1", "Option 2", "Option 3");
comboBox.setOnAction(event -> {
comboBox2.getItems().clear();
for (int i = 0; i < 5; i++) {
comboBox2.getItems().add(comboBox.getValue().toString());
}
});
VBox vBox = new VBox();
vBox.getChildren().addAll(comboBox, comboBox2);
Scene scene = new Scene(vBox);
stage = new Stage();
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) { launch(args); }
}

JavaFx choicebox event handler method doesnt change variable?

I'm new at javafx but I'm writing an app and I want my "to" value to change depending on which option is chosen in the choicebox but my current code always keeps it at 0..help? I want to be able to change the to depending on state
public void start(Stage primaryStage) {
double to=0;
primaryStage.setTitle("ShCal");
GridPane pane = new GridPane();
` pane.setAlignment(Pos.CENTER);
pane.setHgap(10);
pane.setVgap(10);
pane.setPadding(new Insets(25, 25, 25, 25));
Scene scene = new Scene(pane, 300, 275);
//button
Button button=new Button("to");
pane.add(button, 0, 3);
//Pick state
Label State=new Label("State");
pane.add(State,0,0);
//choicebox
ChoiceBox<String> choicesBox=new ChoiceBox<>();
choicesBox.getItems().addAll("NJ","NY");
pane.add(choicesBox,1,0);
//set default
choicesBox.setValue(null);
button.setOnAction(e->getChoice(choicesBox,to));
primaryStage.setScene(scene);
primaryStage.show();
}
private double getChoice(ChoiceBox<String> choicesBox, double tx) {
String state=choicesBox.getValue();
System.out.print(tx);
if(state=="NJ")
{
tx=10/100;
}
System.out.print(state);
return tx;
}
public static void main(String[] args) {
launch(args);
}
}
That is because your to value is of the primitive type double, defined in the scope of your start method. The method getChoice returns the new value, but you are not updating it.
Here are two approaches that you can try:
Define to as member:
private double to = 0;
private double getChoice(ChoiceBox<String> choicesBox) {
String state=choicesBox.getValue();
if(state=="NJ") {
tx=10/100;
}
}
However I personally would prefer a solution that is more inline with JavaFX: Define the to variable as member property:
private DoubleProperty to = new SimpleDoubleProperty(0);
private double getChoice(ChoiceBox<String> choicesBox) {
String state=choicesBox.getValue();
if(state=="NJ") {
tx.setValue(10/100);
}
}
Doing it this way you can then for example have a label displaying the value without the hassle of requiring to update it on each change:
Label lbl = new Label();
lbl.textProperty().bind(to.asString());

TableView is not visible until click

I am using JavaFX and I have a strange problem. The follwing code is in the constructor of a class, which inherits Stage. The code is work in progress.
// this works fine, the chart is displayed
Scene scene = new Scene(lineChart, 1000, 600);
// table is not shown until I click on the window
Scene scene = new Scene(bidTable, 1000, 600);
this.setTitle("Auction chart");
this.setScene(scene);
What do I wrong? No errors and table with content is shown after I click on the window. Before it's just a white window.
EDIT:
I removed the chart just the table:
public class AuctionChart extends Stage {
private final TableView<Bid> bidTable = new TableView<Bid>();
private final TableColumn<Bid, String> bidColumn = new TableColumn<Bid, String>("Bid");
private final TableColumn<Bid, String> utilityColumn = new TableColumn<Bid, String>("Utility");
private final TableColumn<Bid, String> profitColumn = new TableColumn<Bid, String>("Profit");
private final NumberFormat fm = NumberFormat.getCurrencyInstance();
public AuctionChart() {
initialize();
bidTable.getColumns().addAll(bidColumn, utilityColumn, profitColumn);
Scene scene = new Scene(bidTable, 1000, 600);
this.setTitle("Auction chart");
this.setScene(scene);
}
public void setTowns(List<Town> towns) {
bidTable.setItems(FXCollections.observableArrayList(towns.get(0).getGebote()));
}
private void initialize() {
bidColumn.setCellValueFactory(cellData -> new SimpleStringProperty(fm.format(cellData.getValue().getBid())));
utilityColumn
.setCellValueFactory(cellData -> new SimpleStringProperty(fm.format(cellData.getValue().getUtility())));
profitColumn
.setCellValueFactory(cellData -> new SimpleStringProperty(fm.format(cellData.getValue().getProfit())));
}
}
Startup:
AuctionChart stage = new AuctionChart();
stage.setTowns(towns);
stage.show();
Thank you, it isn't a JavaFx Problem. It's an issue with concurrent threads in the application's backend.

Resources