Reputation: 81
I am very new to Java so please be patient with me. I have successfully added buttons, labels and even a progress bar to a listview cell. I need to be able to detect when one of the buttons has been clicked. Adding controls to listview content I managed to get from a couple of posts here the code i am using is shown below
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class ListViewDemo extends Application {
public static class lvCell extends VBox {
Label labelName = new Label();
Label labelPath = new Label();
Label labelElapse = new Label();
Button buttonPlayPause = new Button();
Button buttonStop = new Button();
ImageView ivStop = new ImageView();
ImageView ivPlay = new ImageView();
Pane buttonSpacer = new Pane();
Pane progressBarSpacer = new Pane();
HBox hbDetail = new HBox();
HBox hbProgress = new HBox();
ProgressBar pbProgress = new ProgressBar();
File filePlay;
File fileStop;
double prefWidth = 10;
double prefHeight = 10;
lvCell(String labelText) {
super();
labelName.setText(labelText);
labelName.setMaxWidth(Double.MAX_VALUE);
labelPath.setMaxWidth(0);
labelPath.setText("Path");
pbProgress.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(labelName, Priority.ALWAYS);
HBox.setHgrow(pbProgress, Priority.ALWAYS);
HBox.setMargin(labelName, new Insets(5, 0, 0, 0));
HBox.setMargin(pbProgress, new Insets(0, 0, 0, 0));
labelPath.setVisible(false);
buttonSpacer.setPrefSize(prefWidth, prefHeight);
labelElapse.setPrefSize(50, prefHeight);
labelElapse.setText("Time");;
progressBarSpacer.setPrefSize(prefWidth * 6, prefHeight);
filePlay = new File("src/image/play.png");
fileStop = new File("src/image/stop.png");
Image imagePlay = new Image(filePlay.toURI().toString());
Image imageStop = new Image(fileStop.toURI().toString());
ivPlay.setImage(imagePlay);
ivStop.setImage(imageStop);
ivPlay.setFitHeight(prefHeight);
ivPlay.setFitWidth(prefWidth);
ivStop.setFitHeight(prefHeight);
ivStop.setFitWidth(prefWidth);
buttonPlayPause.setGraphic(ivPlay);
buttonStop.setGraphic(ivStop);
buttonPlayPause.setMaxSize(prefWidth, prefHeight);
buttonStop.setMaxSize(prefWidth, prefHeight);
pbProgress.setMaxHeight(2);
pbProgress.setPrefHeight(2);
hbDetail.getChildren().addAll(buttonPlayPause, buttonStop, buttonSpacer, labelName, labelPath);
hbProgress.getChildren().addAll(progressBarSpacer, pbProgress, labelElapse);
this.getChildren().addAll(hbDetail, hbProgress);
}
}
public Parent createContent() {
BorderPane layout = new BorderPane();
List < lvCell > list = new ArrayList < > ();
for (int i = 0; i < 10; i++) {
list.add(new lvCell("Item " + i));
}
ListView < lvCell > listView = new ListView < lvCell > ();
ObservableList < lvCell > myObservableList = FXCollections.observableList(list);
listView.setItems(myObservableList);
layout.setCenter(listView);
return layout;
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setWidth(300);
stage.setHeight(200);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
}
The screen looks like this:
Any help will be greatly appreciated.
Thanks in advance, and wishing you a peaceful journey.
Yas
Upvotes: 1
Views: 1323
Reputation: 82461
This is not a class well designed to put into a ListView
. An object used as item in a ListView
should contain data; the ListCell
implementation produced by the cellFactory
is responsible for determining the visual representation of the data in the ListView
. This way you avoid the creation of nodes for every object reducing the memory footprint, which is exactly what ListView
is designed for.
The data here contains just the progress and some text; it's displayed in a ProgressBar
and the text
of the cell; an additional button in the cell allows increasing the progress by 0.25 for each click and removing any items reaching a progress of 1.
Data class
public class Data {
private final DoubleProperty progress = new SimpleDoubleProperty();
private final String text;
public Data(String text) {
this.text = text;
}
public double getProgress() {
return progress.get();
}
public void setProgress(double value) {
progress.set(value);
}
public String getText() {
return text;
}
public ObservableValue<? extends Number> progressProperty() {
return progress;
}
}
ListView code
ListView<Data> listView = new ListView<>(someData);
listView.setCellFactory(l -> new ListCell<Data>() {
private final ProgressBar progressBar = new ProgressBar();
private final Button button = new Button("increase");
private final HBox content = new HBox(progressBar, button);
{
button.setOnAction(evt -> {
Data item = getItem();
int index = getIndex();
double progress = item.getProgress() + 0.25;
item.setProgress(progress);
if (progress >= 1) {
getListView().getItems().remove(index);
}
});
}
@Override
protected void updateItem(Data item, boolean empty) {
super.updateItem(item, empty);
progressBar.progressProperty().unbind();
if (item == null) {
setGraphic(null);
setText("");
} else {
setGraphic(content);
setText(item.getText());
progressBar.progressProperty().bind(item.progressProperty());
}
}
});
Upvotes: 2