JavaFX 在 TableView 中显示多行对象

JavaFX display an object with multiple rows in TableView

我正在尝试显示类似于 Twitter 的内容,您可以在其中看到用户、个人资料图片以及消息本身的名称和正文等其他内容,但我似乎想不出类似的方法. This is what I want to display

我想要做的是使用这种格式从数据库中加载所有消息和用户配置文件以及其他详细信息,但我能想到的唯一方法是使用带有 TableColumns 的 TableView,但是这种方法太可怕了,我似乎想不出别的办法了。

This is the only method I found

当您的布局和数据需要类似于包含行和列的电子表格时,TableView 非常有用。你所描绘的不是这样的,所以最好的方法是使用 ListView。 ListView 不只是一列 table,它更像是 windows 的滚动窗格。您创建封闭 window 的布局,ListView 负责将数据加载到每个 window.

要记住的主要事情是,您不会在每次加载数据时都重建布局。在 ListCell 的构造函数中创建一次布局,制作您需要将数据放入 ListCell class 实例变量的小部件,然后您可以覆盖 updateItem() 以将数据放入其中。

为此,ListCell 是一个包含两个 HBox 的 VBox。左边的是头像和用户名,右边的是标题和消息。有一些简单的样式,因为没有它看起来很难看。

public class MessagingListView extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        ListView<ListModel> listView = new ListView<>();
        listView.setCellFactory(lv -> new MessageCell());
        Scene scene = new Scene(listView, 400, 400);
        primaryStage.setScene(scene);
        scene.getStylesheets().add("/css/default.css");
        primaryStage.show();
        ObservableList<ListModel> listModels = FXCollections.observableArrayList();
        listView.setItems(listModels);
        loadData(listModels);
    }


    public class MessageCell extends ListCell<ListModel> {
        HBox graphic;
        ImageView imageView = new ImageView();
        Text nameText = new Text();
        Text titleText = new Text();
        Text messageText = new Text();

        public MessageCell() {
            nameText.getStyleClass().add("label-text");
            titleText.getStyleClass().add("heading-text");
            imageView.setFitWidth(80);
            imageView.setFitHeight(80);
            messageText.setWrappingWidth(260);
            HBox messageBox = new HBox(messageText);
            messageBox.getStyleClass().add("standard-border");
            messageBox.setPadding(new Insets(6));
            VBox leftBox = new VBox(5, imageView, nameText);
            VBox rightBox = new VBox(5, titleText, messageBox);
            leftBox.setAlignment(Pos.TOP_CENTER);
            graphic = new HBox(10, leftBox, rightBox);
        }

        @Override
        public void updateItem(ListModel item, boolean empty) {
            System.out.println("here ");
            if ((item != null) && !empty) {
                System.out.println("updating");
                super.updateItem(item, empty);
                nameText.textProperty().bind(item.userNameProperty());
                titleText.textProperty().bind(item.titleProperty());
                messageText.textProperty().bind(item.messageProperty());
                imageView.imageProperty().bind(item.imageProperty());
                setGraphic(graphic);
            } else {
                setGraphic(null);
            }
        }
    }

    private void loadData(ObservableList<ListModel> listModels) {
        listModels.add(new ListModel("fred",
                                     new Image("https://image.flaticon.com/icons/png/512/145/145859.png"),
                                     "I'm Upset",
                                     "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, " + "totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae " + "vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut " + "odit aut fugit, sed quia consequuntur magni"));
        listModels.add(new ListModel("GeorgeX",
                                     new Image("https://image.flaticon.com/icons/png/512/3048/3048163.png"),
                                     "This is the Title",
                                     "adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam "
                                             + "quaerat voluptatem. Ut enim ad minima veniam"));
    }

    class ListModel {
        StringProperty userName = new SimpleStringProperty("");
        ObjectProperty<Image> image = new SimpleObjectProperty<>();
        StringProperty title = new SimpleStringProperty("");
        StringProperty message = new SimpleStringProperty("");

        public ListModel(String userName, Image image, String title, String message) {
            this.userName.set(userName);
            this.image.set(image);
            this.title.set(title);
            this.message.set(message);
        }

        public StringProperty userNameProperty() {
            return userName;
        }

        public ObjectProperty<Image> imageProperty() {
            return image;
        }

        public StringProperty titleProperty() {
            return title;
        }

        public StringProperty messageProperty() {
            return message;
        }
    }
}

CSS 个元素如下所示:

.root{
    -theme-colour : #017987;
    -theme-deep-colour : derive(-theme-colour, -15%);
    -theme-font-colour : derive(-theme-colour, -50%);
    -theme-deep-font-colour : derive(-theme-font-colour, -50%);
    -theme-light-colour : derive(-theme-colour, +90%);
    -contrast-colour : #f89642;
    -contrast-deep-colour : derive(-contrast-colour, -20%);
    -near-black : #252535;
    -theme-font-family : 'Calibri';
}

.label-text {
    -fx-font-family : -theme-font-family;
    -fx-font-size: 17;
    -fx-fill: -theme-colour;
    -fx-font-weight: bold;
}

.heading-text {
    -fx-font-family : -theme-font-family;
    -fx-font-size: 24;
    -fx-fill: -contrast-colour;
    -fx-stroke: -theme-font-colour;
    -fx-font-weight: bold;
}

.standard-border {
   -fx-border-color : -theme-colour, -theme-deep-colour;
   -fx-border-insets: 0, 0 -1.4 -1.4 0;
   -fx-border-radius : 4px, 6px;
   -fx-border-width : 1.5px, 0 2px 2px 0;
}