Treeview 上的 JavaFX 自动换行,TreeItem/TreeCell

JavaFX word-wrap on a Treeview, TreeItem/TreeCell

我想要一个可折叠的列表,所以我使用的是 TreeView,但较长的字符串会提供水平滚动条而不是自动换行。我试过在 .tree-cell class 上使用 CSS 属性 -fx-wrap-text 但不幸的是似乎没有任何反应。

难道 TreeCell 不应该跨越一行以上吗?如果是这样,还有什么选择?

这是它现在的样子:

test.css

.tree-cell {
        -fx-wrap-text: true;
        -fx-text-fill: blue;
    }

subjects.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.net.URL?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TreeView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication1.FXMLDocumentController">
    <Button fx:id="button" layoutX="182.0" layoutY="14.0" onAction="#handleButtonAction" text="Click Me!" />
    <TextField fx:id="filterSubject" layoutX="21.0" layoutY="14.0" />
    <TreeView fx:id="subjectList" editable="true" layoutX="14.0" layoutY="61.0" prefHeight="200.0" prefWidth="365.0" />
    <stylesheets>
            <URL value="@test.css" />
    </stylesheets>  
</AnchorPane>

subjects.txt - 只是一对文本,第一个是主题,第二个是描述。

1
Somewhat long string that I want to wordwrap.
2
Somewhat long string that I want to wordwrap.
3
Somewhat long string that I want to wordwrap.

FXMLDocumentController.java

package javafxapplication1;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import java.io.*;

public class FXMLDocumentController implements Initializable {


    @FXML
    private TreeView<String> subjectList;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("You clicked me!");
    }

    private void getSubjects(){
        TreeItem<String> subjectRoot = new TreeItem<String> ("Subject");
        subjectRoot.setExpanded(true);
        try {
            BufferedReader fileReader = new BufferedReader(
                    new FileReader("subjects.txt")
            );
            String subject = null;
            String description = null;
            while((subject = fileReader.readLine()) != null) {
                description = fileReader.readLine();
                TreeItem<String> subjectTree = new TreeItem<String> (subject);
                TreeItem<String> descriptionItem = new TreeItem<String> (description);
                subjectTree.getChildren().add(descriptionItem);
                subjectRoot.getChildren().add(subjectTree);

            }  
        } catch(FileNotFoundException e) {
            System.out.println("File not found");
        } catch(IOException e) {
            e.printStackTrace();
        }
        subjectList.setRoot(subjectRoot);
    }
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        getSubjects();
    }      
}

JavaFXApplication1.Java

package javafxapplication1;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class JavaFXApplication1 extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }

}

实际上 CSS class 正在按照您的预期工作。

问题是:TreeView 包含 TreeCell。这些 TreeCell 将环绕其文本,以防它们没有足够的垂直 space 来垂直增长。由于 TreeView 有一个内置的“ScrollPane”,其中的视口将垂直增长,它将为 TreeCell 实例在任何情况下增长提供足够的 space,因此永远不会启用包装。

为避免这种情况,您可以设置 TreeViewcell factory to generate the TreeCell instances manually. And then you can bind the prefWidthProperty of these elements to the widthProperty

例子

public class WrappedTreeView extends Application {

    @Override
    public void start(Stage stage) {
        final Scene scene = new Scene(new Group(), 200, 400);
        Group sceneRoot = (Group) scene.getRoot();

        scene.getStylesheets().add(getClass().getResource("application.css").toString());

        TreeItem<String> root = new TreeItem<>("Root");
        root.setExpanded(true);

        TreeItem<String> childNode1 = new TreeItem<>("I am a very long node - the first one -, my text must be wrapped! If it is not wrapped, it's a problem!");
        TreeItem<String> childNode2 = new TreeItem<>("I am a very long node - the second one -, my text must be wrapped! If it is not wrapped, it's a problem!");
        TreeItem<String> childNode3 = new TreeItem<>("I am a very long node - the third one -, my text must be wrapped! If it is not wrapped, it's a problem!");

        root.getChildren().addAll(childNode1, childNode2, childNode3);
        childNode2.getChildren().add(new TreeItem<>("And I am a very long embedded node, so my text must be wrapped!"));

        TreeView<String> treeView = new TreeView<>(root);
        treeView.setCellFactory(item -> {
            TreeCell<String> treeCell = new TreeCell<String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item != null && !empty)
                        setText(item);
                    else
                        setText("");
                }
            };

            treeCell.prefWidthProperty().bind(treeView.widthProperty().subtract(5.0));
            return treeCell;
        });

        treeView.setMaxWidth(200);

        sceneRoot.getChildren().add(treeView);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }
}

内容application.css

.tree-cell { 
    -fx-wrap-text: true;
    -fx-text-fill: blue;
}

而生成的TreeView:

您可以通过在 treecell cellfactory 中设置树单元的 prefWidth 值(连同树单元的 wraptext 值设置为 true)来执行此操作,这将阻止单元使用 scrollPane 水平扩展。