Implement tags bar in JavaFX

后端 未结 4 1520
无人及你
无人及你 2020-12-01 09:38

Demonstration of answer:(answered May 29 at 3:10 am)

**10/7/2016** you can find the code on GitHub

Actual Que

4条回答
  •  Happy的楠姐
    2020-12-01 10:13

    For the tags you can use a custom styled HBox containing a Text (the tag name) node an a Button (the deletion button (X)). By playing around with the background and the border you can achieve the desired look of the tags.

    The onAction handler of the button should remove the tag from it's parent...

    For the whole tag bar you can use another HBox. Use the appropriate border for the correct look. In addition to the tags add a TextField with no background as last element and set the Hgrow property of that TextField to Priotity.ALWAYS to cover the rest of the available space.

    The onAction handler of this TextField adds new tags and clears the content of the TextField.

    You could e.g. use ControlsFX's autocompletion features with the TextField or implement it on your own for a custom look...

    public class TagBar extends HBox {
    
        private final ObservableList tags;
        private final TextField inputTextField;
    
        public ObservableList getTags() {
            return tags;
        }
    
        public TagBar() {
            getStyleClass().setAll("tag-bar");
            getStylesheets().add(getClass().getResource("style.css").toExternalForm());
            tags = FXCollections.observableArrayList();
            inputTextField = new TextField();
            inputTextField.setOnAction(evt -> {
                String text = inputTextField.getText();
                if (!text.isEmpty() && !tags.contains(text)) {
                    tags.add(text);
                    inputTextField.clear();
                }
            });
    
            inputTextField.prefHeightProperty().bind(this.heightProperty());
            HBox.setHgrow(inputTextField, Priority.ALWAYS);
            inputTextField.setBackground(null);
    
            tags.addListener((ListChangeListener.Change change) -> {
                while (change.next()) {
                    if (change.wasPermutated()) {
                        ArrayList newSublist = new ArrayList<>(change.getTo() - change.getFrom());
                        for (int i = change.getFrom(), end = change.getTo(); i < end; i++) {
                            newSublist.add(null);
                        }
                        for (int i = change.getFrom(), end = change.getTo(); i < end; i++) {
                            newSublist.set(change.getPermutation(i), getChildren().get(i));
                        }
                        getChildren().subList(change.getFrom(), change.getTo()).clear();
                        getChildren().addAll(change.getFrom(), newSublist);
                    } else {
                        if (change.wasRemoved()) {
                            getChildren().subList(change.getFrom(), change.getFrom() + change.getRemovedSize()).clear();
                        }
                        if (change.wasAdded()) {
                            getChildren().addAll(change.getFrom(), change.getAddedSubList().stream().map(Tag::new).collect(Collectors.toList()));
                        }
                    }
                }
            });
            getChildren().add(inputTextField);
        }
    
        private class Tag extends HBox {
    
            public Tag(String tag) {
                getStyleClass().setAll("tag");
                Button removeButton = new Button("X");
                removeButton.setOnAction((evt) -> tags.remove(tag));
                Text text = new Text(tag);
                HBox.setMargin(text, new Insets(0, 0, 0, 5));
                getChildren().addAll(text, removeButton);
            }
        }
    
    }
    

    style.css

    .tag-bar {
        -fx-border-color: blue;
        -fx-spacing: 3;
        -fx-padding: 3;
        -fx-max-height: 30;
    }
    
    .tag-bar .tag {
        -fx-background-color: lightblue;
        -fx-alignment: center;
    }
    
    .tag-bar .tag .button {
        -fx-background-color: transparent;
    }
    
    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button("Sort");
    
        StackPane.setAlignment(btn, Pos.BOTTOM_CENTER);
    
        TagBar tagBar = new TagBar();
    
        btn.setOnAction((ActionEvent event) -> {
            FXCollections.sort(tagBar.getTags());
        });
    
        Button btn2 = new Button("add \"42\"");
        btn2.setOnAction(evt -> {
            if (!tagBar.getTags().contains("42")) {
                tagBar.getTags().add("42");
            }
        });
    
        VBox root = new VBox();
        root.getChildren().addAll(tagBar, btn, btn2);
        root.setPrefSize(300, 400);
    
        Scene scene = new Scene(root);
    
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    

提交回复
热议问题