Java WebView或TextFlow:仅显示适合空间的子字符串

时间:2017-09-11 18:09:55

标签: javafx webview

我正在尝试制作一个显示消息标题和消息正文的TableColumn。它应该具有类似于Gmail的行为。即在一行中显示标题(粗体)和消息正文(常规)。

邮件标题邮件正文。两个字符串都很短 - 可以显示全部
邮件标题现在邮件正文很长。仅显示...的开头 现在邮件标题也很长。此时只有消息标题适合...

问题 LabelText:无法显示两种样式 HBox有两个Text:显示 ... ge Ti ... ..ssage Body ...(所需:消息标题我......)
TextFlowWebView:无法强制setWrap(false)。 JavaFX显示丑陋的多行文字 使用下面的代码基于ColumnWidth计算subString。触发重新计算每列上所有单元格图形的大小。可能但感觉就像为低级语言重新发明轮子一样。

是否有一种构建方式可以在一行中显示两个样式的字符串的开头?

private Double getSubstringLength(String preparedTitle, String headerStyle){

    Text disposable = new Text();
    disposable.setText(preparedTitle);
    disposable.setStyle(headerStyle);

    return disposable.getBoundsInLocal().getWidth();
}

1 个答案:

答案 0 :(得分:2)

您可以使用自定义布局窗格。

sample custom pane

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class MailViewSample extends Application {

    private final ObservableList<Message> data =
        FXCollections.observableArrayList(
            new Message("Jacob", "Message title 1", "Message body. Both strings are short - can display all"),
            new Message("Isabella", "Message title 2", "Now Message body is long. Only display the beginning of this longer body"),
            new Message("Ethan", "Now message title is quite long too. Only message title fits this time no body seen", "Message body not seen")
        );

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

    class MessagePane extends Pane {
        private static final double SPACING = 10;

        private final Label title;
        private final Label body;

        public MessagePane(Label title, Label body) {
            super(title, body);

            this.title = title;
            this.body = body;
        }

        @Override
        protected void layoutChildren() {
            double width = getWidth();
            double height = getHeight();
            double baselineOffset = Math.max(title.getBaselineOffset(), body.getBaselineOffset());

            if (title.prefWidth(-1) + SPACING + body.minWidth(-1) > width) {
                layoutInArea(title, 0, 0, width, height, baselineOffset, HPos.LEFT, VPos.BASELINE);
                layoutInArea(body, 0, 0, 0, 0, baselineOffset, HPos.LEFT, VPos.BASELINE);
            } else {
                double titleWidth = title.prefWidth(-1);
                layoutInArea(title, 0, 0, titleWidth, height, baselineOffset, HPos.LEFT, VPos.BASELINE);
                double bodyWidth = Math.max(0, Math.min(width - (titleWidth + SPACING), body.prefWidth(-1)));
                layoutInArea(body, titleWidth + SPACING, 0, bodyWidth, height, baselineOffset, HPos.LEFT, VPos.BASELINE);
            }
        }
    }

    @Override
    public void start(Stage stage) {
        TableView<Message> table = new TableView<>(data);
        table.setPrefHeight(150);

        TableColumn<Message, String> senderCol = new TableColumn<>("Sender");
        senderCol.setCellValueFactory(new PropertyValueFactory<>("sender"));
        table.getColumns().add(senderCol);

        TableColumn<Message, Message> messageCol = new TableColumn<>("Message");
        messageCol.setCellValueFactory(param -> new SimpleObjectProperty<>(param.getValue()));
        messageCol.setCellFactory(param -> new TableCell<Message, Message>() {
            Label title = new Label();
            Label body = new Label();
            MessagePane messagePane = new MessagePane(title, body);

            {
                title.setStyle("-fx-font-weight: bold;");
                setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            }

            @Override
            protected void updateItem(Message item, boolean empty) {
                super.updateItem(item, empty);

                title.textProperty().unbind();
                body.textProperty().unbind();

                if (empty || item == null) {
                    setGraphic(null);
                } else {
                    title.setText(item.getTitle());
                    body.setText(item.getBody());
                    title.textProperty().bind(item.titleProperty());
                    body.textProperty().bind(item.bodyProperty());

                    setGraphic(messagePane);
                }
            }
        });
        messageCol.setPrefWidth(520);

        table.getColumns().add(messageCol);

        stage.setScene(new Scene(table));
        stage.show();
    }

    public static class Message {
        private final SimpleStringProperty sender;
        private final SimpleStringProperty title;
        private final SimpleStringProperty body;

        private Message(String sender, String title, String body) {
            this.sender = new SimpleStringProperty(sender);
            this.title = new SimpleStringProperty(title);
            this.body = new SimpleStringProperty(body);
        }

        public SimpleStringProperty senderProperty() {
            return sender;
        }

        public String getSender() {
            return sender.get();
        }

        public void setSender(String sender) {
            this.sender.set(sender);
        }
        public SimpleStringProperty titleProperty() {
            return title;
        }

        public String getTitle() {
            return title.get();
        }

        public void setTitle(String title) {
            this.title.set(title);
        }

        public SimpleStringProperty bodyProperty() {
            return body;
        }

        public String getBody() {
            return body.get();
        }

        public void setBody(String body) {
            this.body.set(body);
        }
    }
}