首页 > 解决方案 > 如何将 DoubleProperty 绑定到 JavaFX 中其他两个 DoubleProperty 的差异?

问题描述

我有一个带有自定义单元格的 ListView:这些单元格由一个标签和一个删除按钮组成。

我希望 Label 的 PreferedWidthProperty 始终等于 ListView 的宽度减去按钮的宽度。

因此,在自定义单元类的 updateItem 中,我添加了以下代码:

label.prefWidthProperty().bind(listViewWidth.subtract(delButton.widthProperty()));

但是这样一来, Button 的宽度并没有减去,标签的宽度等于 ListView 的宽度:出现水平滚动条,并且按钮超出了框架。

经过一些测试,在执行此代码时按钮的宽度似乎等于零(因为按钮本身尚未显示)但它永远不会重新计算:它始终保持为零,因此 substration 总是等于 ListView 的未修改宽度。

如何强制绑定始终等于减去这些对象的当前值?

编辑:我想要的是这个非常简单的外观: 在此处输入图像描述

那是 :

我得到的是: 在此处输入图像描述

文本换行好了....但是 Label 具有 ListView 的宽度,因此按钮超出了框架,需要滚动以删除该行,这看起来有点荒谬。

我的工厂很简单:

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;
    }
});

“DeletableCell”从以下 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>

所以它是一个非常简单的带有标签和按钮的 HBox,我希望标签具有包含列表视图的宽度减去按钮的宽度。

我需要设置 PreferedWidth 属性,因为没有它,文本将不会换行,而且我会有更丑陋的东西:只有一条长线的标签带有巨大的水平滚动条。所以我环顾四周寻找如何不拥有它,发现你需要设置 PreferedWidth 因为 wrapText="true" 不足以做到这一点。

标签: javafx

解决方案


设置MaxWidthProperty单元格的HBox应该可以做到这一点。我们将该值绑定到宽度ListView减去ListView填充宽度:

maxWidthProperty().bind(listView.widthProperty().subtract(25));

这是一个演示它的快速示例程序。这确实在 Java(而不是 FXML)中构建了自定义ListCell,但总体思路是相同的。

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();
    }
}

结果:

截屏


推荐阅读