答案示范:( 5月29日凌晨3:10回答)
**10/7/2016** you can find the code on
GitHub
回答前的实际问题:( 5月22日19:53问)
标题可能不是很好,但我想要做的是在JavaFX中这样的事情:
实施例
的YouTube :
StackOverFlow(具有并自动完成):
问题: 我不需要写代码。相反,我想知道如何使用JavaFX和一些想法实现这一点。
答案 0 :(得分:12)
对于标签,您可以使用包含HBox
(标签名称)节点的自定义样式Text
和Button
(删除按钮(X))。通过使用背景和边框,您可以获得所需的标签外观。
按钮的onAction
处理程序应从其父级中移除标记...
对于整个标记栏,您可以使用其他HBox
。使用适当的边框以获得正确的外观。除了代码之外,添加一个没有背景的TextField
作为最后一个元素,并将Hgrow
的{{1}}属性设置为TextField
以覆盖剩余的可用空间。< / p>
此Priotity.ALWAYS
的{{1}}处理程序会添加新标记并清除onAction
的内容。
你可以,例如使用ControlsFX与TextField
的自动完成功能,或者自己实现自定义外观......
TextField
TextField
public class TagBar extends HBox {
private final ObservableList<String> tags;
private final TextField inputTextField;
public ObservableList<String> 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<? extends String> change) -> {
while (change.next()) {
if (change.wasPermutated()) {
ArrayList<Node> 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);
}
}
}
答案 1 :(得分:6)
简单实现此代码!
import ....
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
HBox tagsPane = new HBox(10);
tagsPane.setStyle("-fx-border-color: #F1F1F1;" +
" -fx-border-width: 1px;" +
" -fx-border-radius: 10;" +
" -fx-border-insets: 5");
root.setBottom(tagsPane);
TextField textField = new TextField();
textField.setPromptText("Tag name - ENTER to add");
textField.setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.ENTER) {
tagButton(tagsPane, textField.getText());
textField.clear();
}
});
root.setTop(textField);
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 450, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
//little image as 15x15 for example
Image toUse = new Image("sample/delete.png");
//box is the pane where this buttons will be placed
public void tagButton(HBox box,String tag){
ImageView closeImg = new ImageView(toUse);
Button result = new Button(tag,closeImg);
result.setPrefHeight(20);
result.setContentDisplay(ContentDisplay.RIGHT);
result.setOnAction(event -> box.getChildren().remove(result));
box.getChildren().add(result);
}
}
此外,如果您需要不同的事件来点击标签并单击“X”,您可以像这样实现tagButton:
public void tagButton(HBox box,String tag){
ImageView closeImg = new ImageView(toUse);
HBox button = new HBox();
button.setStyle("-fx-padding:4;" +
" -fx-border-width: 2;" +
" -fx-border-color: black;" +
" -fx-border-radius: 4;" +
" -fx-background-color: f1f1f1;" +
" -fx-border-insets: 5;");
button.setPrefHeight(20);
button.getChildren().addAll(new Label(tag),closeImg);
closeImg.setOnMouseClicked(event ->
box.getChildren().remove(button)
);
button.setOnMouseClicked(event -> {
//doSomethig
});
box.getChildren().add(button);
}
答案 2 :(得分:4)
这也是我的版本
它有点长,这就是原因。
但总结一下。你需要一个
1:FlowPane
用于容器,你不必担心包装,它会自行包裹,包括垂直或水平。
2:Label
当然是您的文字,其中有GraphicProperty
3:Path
- 您可以使用Button
,并为其添加Shape
或Image
,但这将是很多节点,因此我使用了Path
我画了一个X
红色按钮。
其余的是造型为您喜欢的颜色
修改强> 这样的事情?
你可以设置它以获得输出
setFont(Font.font("Serif Regular", FontWeight.SEMI_BOLD,12));
在TextField
答案 3 :(得分:3)
这是一个标签栏的基本示例(我写了一些代码,因为我觉得它更容易理解)。对于其他自动完成功能,您可以使用例如ControlsFx,正如fabian已经提到的那样。
public class CloseTag extends HBox implements Comparable<CloseTag> {
private Label label;
private Label closeIcon;
public CloseTag(String text) {
setStyle("-fx-padding:8;");
Text icon = GlyphsDude.createIcon(FontAwesomeIcon.TIMES_CIRCLE);
closeIcon = new Label(null, icon);
label = new Label(text, new StackPane(closeIcon));
label.setContentDisplay(ContentDisplay.RIGHT);
getChildren().add(label);
}
public void setOnCloseAction(EventHandler<? super MouseEvent> action) {
closeIcon.setOnMouseClicked(action);
}
public String getText() {
return label.getText();
}
@Override
public int compareTo(CloseTag other) {
return getText().compareTo(other.getText());
}
}
public class TagPane extends FlowPane {
private TextField textField;
public TagPane() {
setStyle("-fx-padding:8;" + "-fx-hgap:10;");
setOnMouseClicked(evt -> onMouseClickedd(evt));
textField = new TextField();
textField.setOnKeyPressed(evt -> onKeyPressed(evt, textField));
}
private void onMouseClickedd(MouseEvent mouseEvent) {
if (mouseEvent.getTarget() != this || textField.getParent() != null ) {
return;
}
getChildren().add(textField);
textField.requestFocus();
}
private void onKeyPressed(KeyEvent evt, TextField textField) {
if (evt.getCode() == KeyCode.ENTER || evt.getCode() == KeyCode.TAB) {
createTag(textField.getText());
textField.clear();
}
}
private void createTag(String text) {
CloseTag tag = new CloseTag(text);
tag.setOnCloseAction(evt -> removeTag(tag));
getChildren().remove(textField);
getChildren().add(tag);
}
private void removeTag(CloseTag tag) {
getChildren().remove(tag);
}
}