I have been trying to unselect or clear the value of choicebox, from when a user select another option within the same box. When I select a Brand of car and then select another all choices are displayed, if I select the same one the images just duplicate and the 1st of images are left blank and only the buttons remain... I have tried/ setValue null/isVisible/setVisible/ but the space of the buttons are still there....I even tried to do getchildren remove ... I am lost..
public class HelloController implements Initializable {
private Stage stage;
private Scene scene;
private Parent root;
@FXML private Label lbMake;
@FXML private Label lbBody;
@FXML private Label lbColor;
@FXML private Label lbEngine;
@FXML private Label lbPerformance;
@FXML private Label lbPrice;
@FXML private TilePane tilePaneMain;
@FXML private ChoiceBox<String> cbMake;
@FXML private ChoiceBox<String> cbColor;
@FXML private ChoiceBox<String> cbPerformance;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
displayGallery();
cbMake.getItems().addAll("Clear Choice","Aston Martin","BMW","Ferrari","Genesis","Hummer","Lamborghini","Lincoln","Lucid","Maserati","Maybach","McLaren","Rolls-Royce","Tesla");
cbMake.setOnAction(this::getMake);
cbColor.getItems().addAll("Clear Choice","black","blue","green","orange","red","white","yellow","gold");
cbColor.setOnAction(this::getColor);
cbPerformance.getItems().addAll("Clear Choice","2.3","2.5","2.7","3.0","3.6","3.8","4.2");
cbPerformance.setOnAction(this::getPerformance);
}
// This is the constructors for the data.
Cars car0 = new Cars("Aston Martin", "220000.00", "black", "8", "3.6", new ImageView(new Image(getClass().getResourceAsStream("/car0.jpg"))),"yes");
Cars car1 = new Cars("Aston Martin", "220000", "blue", "8", "3.6", new ImageView(new Image(getClass().getResourceAsStream("/car1.jpg"))),"no");
Cars car2 = new Cars("Aston Martin", "220000", "green", "8", "3.6", new ImageView(new Image(getClass().getResourceAsStream("/car2.jpg"))),"no");
Cars car3 = new Cars("Aston Martin", "220000", "red", "8", "3.6", new ImageView(new Image(getClass().getResourceAsStream("/car3.jpg"))),"yes");
Cars car4 = new Cars("Cadillac", "110000", "blue", "0", "4.8", new ImageView(new Image(getClass().getResourceAsStream("/car4.jpg"))),"no");
Cars car5 = new Cars("Cadillac", "110000", "red", "0", "4.8", new ImageView(new Image(getClass().getResourceAsStream("/car5.jpg"))),"no");
Cars car6 = new Cars("Maserati", "200000", "black", "8", "3.8", new ImageView(new Image(getClass().getResourceAsStream("/car6.jpg"))),"no");
Cars car7 = new Cars("Maserati", "200000", "blue", "8", "3.8", new ImageView(new Image(getClass().getResourceAsStream("/car7.jpg"))),"no");
Cars car8 = new Cars("Maserati", "200000", "red", "8", "3.8", new ImageView(new Image(getClass().getResourceAsStream("/car8.jpg"))),"no");
Cars car9 = new Cars("Maserati", "200000", "white", "8", "3.8", new ImageView(new Image(getClass().getResourceAsStream("/car9.jpg"))),"yes");
Cars car10 = new Cars("Lamborghini", "400000", "black", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car10.jpg"))),"no");
Cars car11 = new Cars("Lamborghini", "400000", "black", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car11.jpg"))),"yes");
Cars car12 = new Cars("Lamborghini", "400000", "blue", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car12.jpg"))),"yes");
Cars car13 = new Cars("Lamborghini", "400000", "green", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car13.jpg"))),"no");
Cars car14 = new Cars("Lamborghini", "400000", "white", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car14.jpg"))),"no");
Cars car15 = new Cars("Lamborghini", "400000", "yellow", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car15.jpg"))),"no");
Cars car16 = new Cars("McLaren", "365000", "yellow", "8", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car16.jpg"))),"no");
Cars car17 = new Cars("McLaren", "365000", "blue", "8", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car17.jpg"))),"no");
Cars car18 = new Cars("McLaren", "365000", "green", "8", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car18.jpg"))),"no");
Cars car19 = new Cars("McLaren", "365000", "black", "8", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car19.jpg"))),"no");
Cars car20 = new Cars("McLaren", "365000", "red", "8", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car20.jpg"))),"no");
Cars car21 = new Cars("McLaren", "400000", "orange", "10", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car21.jpg"))),"yes");
Cars car22 = new Cars("Ferrari", "400000", "black", "12", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car22.jpg"))),"yes");
Cars car23 = new Cars("Ferrari", "400000", "blue", "12", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car23.jpg"))),"yes");
Cars car24 = new Cars("Ferrari", "400000", "red", "8", "2.7", new ImageView(new Image(getClass().getResourceAsStream("/car24.jpg"))),"no");
Cars car25 = new Cars("Ferrari", "400000", "white", "12", "2.5", new ImageView(new Image(getClass().getResourceAsStream("/car25.jpg"))),"yes");
Cars car26 = new Cars("Ferrari", "400000", "white", "8", "2.7", new ImageView(new Image(getClass().getResourceAsStream("/car26.jpg"))),"no");
Cars car27 = new Cars("Ferrari", "400000", "yellow", "8", "2.7", new ImageView(new Image(getClass().getResourceAsStream("/car27.jpg"))),"no");
Cars car28 = new Cars("Lincoln", "365000", "black", "12", "4.2", new ImageView(new Image(getClass().getResourceAsStream("/car28.jpg"))),"no");
Cars car29 = new Cars("Lincoln", "365000", "gray", "12", "4.2", new ImageView(new Image(getClass().getResourceAsStream("/car29.jpg"))),"no");
Cars car30 = new Cars("Hummer", "180000", "blue", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car30.jpg"))),"no");
Cars car31 = new Cars("Hummer", "180000", "orange", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car31.jpg"))),"no");
Cars car32 = new Cars("Hummer", "180000", "white", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car32.jpg"))),"no");
Cars car33 = new Cars("Hummer", "180000", "gray", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car33.jpg"))),"no");
Cars car34 = new Cars("Hummer", "180000", "white", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car34.jpg"))),"no");
Cars car35 = new Cars("Lucid", "150000", "blue", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car35.jpg"))),"no");
Cars car36 = new Cars("Lucid", "150000", "red", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car36.jpg"))),"no");
Cars car37 = new Cars("Lucid", "150000", "white", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car37.jpg"))),"no");
Cars car38 = new Cars("Rivian", "100000", "red", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car38.jpg"))),"no");
Cars car39 = new Cars("Rivian", "100000", "blue", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car39.jpg"))),"no");
Cars car40 = new Cars("Maybach", "400000", "red", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car40.jpg"))),"no");
Cars car41 = new Cars("BMW", "250000", "gold", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car41.jpg"))),"no");
Cars car42 = new Cars("Rolls-Royce", "500000", "gold", "0", "3.0", new ImageView(new Image(getClass().getResourceAsStream("/car42.jpg"))),"no");
Cars car43 = new Cars("Genesis", "300000", "white", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car43.jpg"))),"yes");
Cars car44 = new Cars("Tesla", "50000", "gray", "0", "2.3", new ImageView(new Image(getClass().getResourceAsStream("/car44.jpg"))),"no");
// This is adding the constructor to an Array
public ArrayList<Cars> getList() {
ArrayList<Cars> carList = new ArrayList<>();
return carList;
}
// This display the gallery to the opening scene.
public void displayGallery() {
int i =0;
for (i = 0; i < getList().size(); i++) {
ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream("/car" + i + ".jpg")));
imageView.setFitWidth(200);
imageView.setFitHeight(155);
Button btnGallery = new Button(Integer.toString(i),imageView);
int finalI = i;
btnGallery.setOnMouseEntered(event->{
//btnGallery.setTextFill(Color.PURPLE);
lbMake.setText(getList().get(finalI).getMake());
lbColor.setText(getList().get(finalI).getColor());
lbPerformance.setText(getList().get(finalI).getPerformance());
lbPrice.setText(getList().get(finalI).getPrice());
lbEngine.setText(getList().get(finalI).getCylinder());
lbBody.setText(getList().get(finalI).getIsConvertable());
});
btnGallery.setOnMouseExited(event->{
//btnGallery.setTextFill(Color.BLACK);
lbMake.setText("");
lbColor.setText("");
lbPerformance.setText("");
lbPrice.setText("");
lbEngine.setText("");
lbBody.setText("");
});
btnGallery.setOnAction(ae-> {
try {
String btnText = btnGallery.getText();
ArrayList<Cars> passList = getList();
FXMLLoader loader = new FXMLLoader(getClass().getResource("payment-view.fxml"));
root = loader.load();
PaymentController paymentController = loader.getController();
paymentController.displayName(btnText);
paymentController.getArrayList(passList);
stage = (Stage) ((Node) ae.getSource()).getScene().getWindow();
scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
//tilePaneMain.getChildren().add(btnGallery);
}
}
// Display results but doesn't remove previous selection once another is made, if another enter //image description herechoice box selction is made,if images duplicate then empty buttons //remain.
private void getMake(ActionEvent actionEvent) {
for (int index = 0; index < getList().size();index++){
if ((getList().get(index).getMake().contains(cbMake.getValue()))){
getList().get(index).getImage().setFitWidth(175);
getList().get(index).getImage().setFitHeight(150);
Button btnMake = new Button();
btnMake.setGraphic(getList().get(index).getImage());
tilePaneMain.getChildren().add(btnMake);
}
}
}
private void getColor(ActionEvent actionEvent) {
for (int index = 0; index < getList().size();index++){
if ((getList().get(index).getColor().contains(cbColor.getValue()))){
getList().get(index).getImage().setFitWidth(175);
getList().get(index).getImage().setFitHeight(150);
Button btnMake = new Button();
btnMake.setGraphic(getList().get(index).getImage());
tilePaneMain.getChildren().add(btnMake);
}
}
}
private void getPerformance(ActionEvent actionEvent) {
for (int index = 0; index < getList().size();index++){
if ((getList().get(index).getPerformance().contains(cbPerformance.getValue()))){
getList().get(index).getImage().setFitWidth(175);
getList().get(index).getImage().setFitHeight(150);
Button btnMake = new Button();
btnMake.setGraphic(getList().get(index).getImage());
tilePaneMain.getChildren().add(btnMake);
}
}
}
}
You are implementing a set of filters that can be applied to a list of items to be displayed.
The main issues in your current code (there are likely others) are these:
tilePaneMain.getChildren().clear()
. Otherwise what you are doing is keeping the gallery display for the previous selection.initialize
method you call displayGallery
to do all this work to create buttons with custom actions, then you never use them as this line is commented out: //tilePaneMain.getChildren().add(btnGallery);
.I would consider a ControlsFX GridView for this. That is backed by an ObservableList
which can be a FilteredList
where the filter is applied dynamically based on changes in search suggestions, similarly to the way filtering works in a ListView.
It is best to use a filtered list and update the filters for the list to apply them, even if you don't use the ControlsFX GridView
.
In this example, I will demonstrate creating and applying filters to show items in a filtered gallery. I won't use a ControlsFX GridView
(though that would be preferred) as I don't want to add a dependency here on third party software. A ListView
could be used in place of a GridView
, but that might be less close to the behavior you eventually want, so I won't demonstrate that here.
Instead, what I will do is take a TilePane
and filter the content shown there. The filtering and implementation provided is less efficient than using a virtualized control with cells such as a ListView
or GridView
, but it is OK for a small example such as this. The TilePane
based solution is also closer to your original implementation than the virtualized control style solution.
I also won't use FXML or external CSS files to keep things more self-contained.
You need to model a car dealership and provide a UI for it.
For that you need a Car type:
record Car(int vin, String make, NamedColor namedColor) {}
A way to represent the colors of the cars:
import javafx.scene.paint.Color;
record NamedColor(String name, Color color) implements Comparable<NamedColor> {
private static final Color INDIA_INK = Color.web("#3c3f4a");
public static final NamedColor BLACK = new NamedColor("black", INDIA_INK);
public static final NamedColor BLUE = new NamedColor("blue", Color.BLUE);
public static final NamedColor GREEN = new NamedColor("green", Color.GREEN);
public static final NamedColor RED = new NamedColor("red", Color.RED);
@Override
public int compareTo(NamedColor o) {
return name.compareTo(o.name);
}
@Override
public String toString() {
return name;
}
}
A car dealership with cars and some info about them:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
class Dealership {
private final ObservableList<Car> cars = FXCollections.observableArrayList(
new Car(1, "Aston Martin", NamedColor.BLACK),
new Car(2, "Aston Martin", NamedColor.BLUE),
new Car(3, "Aston Martin", NamedColor.GREEN),
new Car(4, "Aston Martin", NamedColor.RED),
new Car(5, "Cadillac", NamedColor.BLUE),
new Car(6, "Cadillac", NamedColor.RED),
new Car(7, "Maserati", NamedColor.BLACK),
new Car(8, "Maserati", NamedColor.BLUE)
);
ObservableList<Car> getCars() {
return cars;
}
List<NamedColor> getColors() {
return cars.stream()
.map(Car::namedColor)
.distinct()
.sorted()
.toList();
}
List<String> getMakes() {
return cars.stream()
.map(Car::make)
.distinct()
.sorted()
.toList();
}
}
A way to display an individual car:
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.Background;
import javafx.scene.layout.StackPane;
class CarPanel extends StackPane {
private static final String CSS_DATA_URL = "data:text/css,";
private static final String CSS = CSS_DATA_URL + // language=CSS
"""
.car-info .text {
-fx-font-size: 30px;
-fx-fill: cornsilk;
}
""";
CarPanel(Car car) {
getStylesheets().add(CSS);
getStyleClass().add("car-info");
setBackground(
Background.fill(
car.namedColor().color()
)
);
setPadding(new Insets(10));
Label label = new Label(
"""
Make: %s
Vin: %d
Color: %s
""".formatted(car.make(), car.vin(), car.namedColor().name())
);
StackPane.setAlignment(label, Pos.TOP_LEFT);
getChildren().add(label);
}
}
A showroom for the cars available in the dealership:
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.layout.TilePane;
class Showroom extends TilePane {
private final ObservableList<Car> cars;
Showroom(ObservableList<Car> cars) {
this.cars = cars;
setHgap(10);
setVgap(10);
setPrefColumns(4);
setPadding(new Insets(10));
showCars();
cars.addListener((ListChangeListener<Car>) c ->
showCars()
);
}
private void showCars() {
// for debug info if you need it . . .
// System.out.println(cars);
getChildren().clear();
cars.stream().map(CarPanel::new).forEach(
carPane -> getChildren().add(carPane)
);
}
}
Some controls to filter the cars shown:
import javafx.collections.transformation.FilteredList;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
class FilterControls {
private final FilteredList<Car> filteredCars;
private final ChoiceBox<String> makeChoice = new ChoiceBox<>();
private final ChoiceBox<NamedColor> colorChoice = new ChoiceBox<>();
private final HBox filterControls;
FilterControls(Dealership dealership) {
filteredCars = new FilteredList<>(dealership.getCars());
makeChoice.getItems().add(null);
makeChoice.getItems().addAll(dealership.getMakes());
makeChoice.setOnAction(e -> updateFilter());
colorChoice.getItems().add(null);
colorChoice.getItems().addAll(dealership.getColors());
colorChoice.setOnAction(e -> updateFilter());
filterControls = new HBox(10, makeChoice, colorChoice);
filterControls.setPadding(new Insets(10));
}
Parent getUI() {
return filterControls;
}
private void updateFilter() {
filteredCars.setPredicate(car ->
isMakeMatch(car, makeChoice.getValue())
&& isColorMatch(car, colorChoice.getValue())
);
}
private boolean isMakeMatch(Car car, String make) {
return make == null || make.equals(car.make());
}
private boolean isColorMatch(Car car, NamedColor color) {
return color == null || color.equals(car.namedColor());
}
FilteredList<Car> getFilteredCars() {
return filteredCars;
}
}
And an application to tie it all together:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class CarDealershipApp extends Application {
private final Dealership dealership = new Dealership();
@Override
public void start(Stage stage) throws Exception {
FilterControls filterControls = new FilterControls(dealership);
BorderPane layout = new BorderPane();
layout.setTop(filterControls.getUI());
layout.setCenter(
new Showroom(
filterControls.getFilteredCars()
)
);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Then you get something like this: