简体   繁体   English

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

[英]JavaFX word-wrap on a Treeview, TreeItem/TreeCell

I want to have a collapsible list so I'm using a TreeView, but longer strings are giving horizontal scrollbars instead of word wrapping.我想要一个可折叠的列表,所以我使用的是 TreeView,但更长的字符串会提供水平滚动条而不是自动换行。 I've tried using the CSS property -fx-wrap-text on the .tree-cell class but unfortunately nothing seems to happen.我试过在.tree-cell类上使用 CSS 属性-fx-wrap-text但不幸的是似乎没有发生任何事情。

Are TreeCell s not meant to span more than one line? TreeCell不打算跨越多条线吗? What alternative is there if that's the case?如果是这样,还有什么替代方案?

Here's an image of what it looks like now:这是它现在的样子:

在此处输入图片说明

test.css测试文件

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

subjects.fxml主题.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 - just pairs of text where the first is subject, and second is description. subject.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 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 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);
    }

}

Actually the CSS class is working as you expect.实际上,CSS 类正在按您的预期工作。

The problem is: The TreeView contains TreeCell s.问题是: TreeView包含TreeCell s。 These TreeCell s will wrap its text, in case of they will have not enough vertical space to grow vertically.这些TreeCell s 将包裹它的文本,以防它们没有足够的垂直空间来垂直增长。 As the TreeView has a built in " ScrollPane " which ones view-port will grow vertically, it will provide enouth space for the TreeCell instances in any case to grow, therefore the wrapping will never be enabled.由于TreeView有一个内置的“ ScrollPane ”,它的视口将垂直增长,因此它将在任何情况下为TreeCell实例的增长提供足够的空间,因此永远不会启用包装。

To avoid this you could set the cell factory to generate the TreeCell instances manually.为避免这种情况,您可以将单元工厂设置为手动生成TreeCell实例。 And then you can bind the prefWidthProperty of these elements to the widthProperty of the TreeView .然后你就可以绑定prefWidthProperty这些元素到的widthProperty了的TreeView

Example例子

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

The content of application.css application.css 的内容

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

And the generated TreeView :和生成的TreeView

在此处输入图片说明

您可以通过在 treecell cellfactory 中设置树单元格的 prefWidth 值(以及将树单元格的 wraptext 值设置为 true)来做到这一点,然后这将阻止单元格使用滚动窗格水平扩展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM