我想为用户提供在数据库中搜索的功能。他们应该能够在一列上按文本搜索,在另一列上按日期搜索。但我不想在UI中创建两个单独的字段,我想将它们组合在一个TextField中。 JFXtras中的LocalDateTextField对此非常有用,因为它允许使用方便的选择器选择日期,但也允许输入文本。但是,它会自动解析输入,如果无法将其解析为LocalDate,则该字段将清除(按照定义)。
我的问题是:我可以保留文本,如果有的话我得到LocalDate,或者如果LocalDate字段为null,那么我只得到文本?我试过尝试使用setParseErrorCallback(试图在那里设置文本属性),但似乎删除发生在某个地方。我可以在常规TextField旁边放一个按钮,用LocalDatePicker调用PopOver,但我不确定如何复制它的外观。我如何设计它以使popover像Button一样用渐变着色?我已经尝试过picker.getStyleClass().add("button")
,但这会继续悬停发光和填充。
以下是LocalDateTextField选择器的外观:
请注意填充,渐变以及它如何直接位于文本字段下方。这是按下Button时调用的PopOver中的LocalDatePicker:
总结:我可以更改LocalDateTextField的行为,如果是,那么如何,如果没有那么我如何设置我自己的实现看起来相同?我已经尝试过查看源文件了,但我无法理解那里的魔法发生在哪里。
答案 0 :(得分:0)
结束制作我自己的SearchTextField。有一个HBox,把TextField和Button放在那里,Button用LocalDatePicker调用PopOver,选择器用来自JFXtras的以下css设置样式:
.LocalDatePicker {
-fx-background-color: -fx-body-color;
-fx-background-insets: 0 0 -1 0,0,1,2;
-fx-background-radius: 5,5,4,3;
-fx-padding: 0.466667em 0.333333em 0.35em 0.333333em;
-fx-text-fill: -fx-text-base-color;
}
然后添加了一些监听器以提供所需的逻辑并完成所有操作。
这里是代码(抱歉)
package view.elements;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.util.Duration;
import jfxtras.scene.control.LocalDatePicker;
import org.controlsfx.control.PopOver;
import org.controlsfx.glyphfont.FontAwesome;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class SearchTextField extends HBox {
private final TextField field = new TextField();
private final LocalDatePicker picker = new LocalDatePicker();
private final PopOver over = new PopOver(picker);
private final Button searchButton = new Button("Искать");
private final StringProperty promptTextProperty = new SimpleStringProperty();
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
public SearchTextField() {
super();
field.promptTextProperty().bind(promptTextProperty);
field.setPrefColumnCount(20);
over.setArrowSize(0);
over.setArrowLocation(PopOver.ArrowLocation.TOP_CENTER);
picker.getStylesheets().add(SearchTextField.class.getResource("datefield.css").toExternalForm());
picker.getStyleClass().add("LocalDatePicker");
picker.prefWidthProperty().bind(this.widthProperty());
picker.setMode(LocalDatePicker.Mode.SINGLE);
picker.setAllowNull(true);
final Button showPicker = new Button();
showPicker.setGraphic(MethodFX.getFontAwesome().create(FontAwesome.Glyph.CALENDAR_ALT));
showPicker.setOnAction(event -> {
if (over.isShowing())
over.hide();
else
over.show(field, -2);
});
field.textProperty().addListener((obs, oldText, newText) -> {
if(newText.matches("(^(((0[1-9]|1[0-9]|2[0-8])[.](0[1-9]|1[012]))|((29|30|31)[.](0[13578]|1[02]))|((29|30)[.](0[4,6,9]|11)))[.](19|[2-9][0-9])\\d\\d$)|(^29[.]02[.](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)"))
picker.localDateProperty().setValue(LocalDate.parse(newText, dateFormatter));
else
picker.localDateProperty().setValue(null);
});
picker.localDates().addListener((ListChangeListener<LocalDate>) c -> {
while(c.next() && c.wasAdded()) {
field.setText(dateFormatter.format(c.getAddedSubList().get(0)));
}
over.hide();
});
field.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (newValue && over.isShowing())
over.hide();
});
this.setSpacing(4);
this.getChildren().addAll(field, showPicker, searchButton);
}
public String getText() { return field.getText(); }
public LocalDate getLocalDate() { return picker.getLocalDate(); }
public void hidePicker(Duration duration) { if (over.isShowing()) over.hide(duration); }
public void setOnSearch(EventHandler<ActionEvent> eventHandler) { searchButton.setOnAction(eventHandler); }
public StringProperty promptTextProperty() {
return promptTextProperty;
}
public void setPromptText(String value) { promptTextProperty.setValue(value); }
public String getPromptText() { return promptTextProperty.getValue(); }
}