Reputation: 305
I have a ListView with custom cells : these cells are made of a label and a delete button.
I want the PreferedWidthProperty of the Label to be constantly equal to the width of the ListView minus the width of the button.
Hence, in the updateItem of the custom cell class, I added the following code :
label.prefWidthProperty().bind(listViewWidth.subtract(delButton.widthProperty()));
But with this, the width of the Button is not substracted and the width of the label is equal to the width of the ListView : a horizontal scroll bar appears and the button is out of the frame.
After a bit of testing, it appears the width of the button is equal to zero at the moment this code is executed (since the button itself is not shown yet) but it is never recalculated : it always stays zero, hence the substration is always equal to the ListView's unmodified width.
How to force the binding to be constantly equal to the substraction of the current values of these objects?
Edit :
What I want is this extremely simple look :
That is :
The text wraps alright.... but the Label has the width of the ListView so the button is out of the frame and needs to be scrolled to to delete the line, which looks kind of ridiculous.
My factory is very simple :
fx_listBoxMain.setCellFactory(new Callback<ListView<String>, ListCell<String>>()
{
@Override
public ListCell<String> call(ListView<String> param)
{
DeletableCell result = null;
try
{
result = new DeletableCell();
}
catch (IOException e)
{
//Deal with that case as soon as the basics are working
}
return result;
}
});
The "DeletableCell" is inflated from the following fxml :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<HBox fx:controller="DeletableCellController" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label fx:id="fx_labelView" wrapText="true"/>
<Button fx:id="fx_delButton" mnemonicParsing="false" text="X" onAction="#deleteAction" />
</children>
</HBox>
So it is a very straightforward HBox with a Label and a Button and I want the Label to have the width of the containing listview minus the width of the button.
I need to set the PreferedWidth property because without that, the text will not wrap and I will have something even uglier : labels of only one long line with a huge horizontal scrollbar. So I looked around SO to find how not to have that and found out you needed to set PreferedWidth because wrapText="true" is not sufficient for that.
Upvotes: 0
Views: 697
Reputation: 10253
Setting the MaxWidthProperty
of the cell's HBox
should accomplish this. We would bind that value to the width of the ListView
minus the width the ListView
padding:
maxWidthProperty().bind(listView.widthProperty().subtract(25));
Here is a quick sample program that demonstrates it. This does build the custom ListCell
in Java (instead of FXML), but the general idea would be the same.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ListCellWrap extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
ListView<String> listView = new ListView<>();
// Sample data
listView.getItems().addAll(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
);
// Override the ListCell
listView.setCellFactory(lv -> new ListCell<String>() {
// Create our cell's layout
final Label label = new Label() {{
setWrapText(true);
}};
final Button button = new Button("X") {{
setOnAction(event -> {
// Processing here
});
}};
final HBox root = new HBox(5, label, button) {{
maxWidthProperty().bind(listView.widthProperty().subtract(25));
}};
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setGraphic(null);
} else {
label.setText(item);
setGraphic(root);
}
}
});
root.getChildren().add(listView);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
The Result:
Upvotes: 2