|
我已经实现了一个ComboBox,其列表由ComboBox TextField中的输入过滤.它可以正常工作,因为你可能期望这种控件的过滤器工作.列表中显示列表中以输入文本开头的每个项目.
我只有一个小问题.如果我从列表中选择一个项目,然后尝试删除文本字段中的最后一个字符,则没有任何反应.如果我从列表中选择一个项目,然后尝试删除除最后一个之外的任何其他字符,则会删除整个字符串.只有这是我在ComboBox中做的第一件事时才会出现这两个问题.如果我先在组合框中写一些东西,或者我第二次选择一个项目,则不会出现所描述的任何问题.
对我来说真正奇怪的是,这些问题似乎是由谓词设置引起的(如果我注释掉setPredicate的调用,一切正常).这很奇怪,因为我认为这应该只影响为谓词设置的列表.它不应该影响ComboBox的其余部分.
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class TestInputFilter extends Application {
public void start(Stage stage) {
VBox root = new VBox();
ComboBox
编辑:我试图在绝望的尝试中覆盖关键监听器来解决问题:
cb.getEditor().addEventFilter(KeyEvent.KEY_PRESSED,e -> {
TextField editor = cb.getEditor();
int caretPos = cb.getEditor().getCaretPosition();
StringBuilder text = new StringBuilder(cb.getEditor().getText());
// If BACKSPACE is pressed we remove the character at the index
// before the caret position.
if (e.getCode().equals(KeyCode.BACK_SPACE)) {
// BACKSPACE should only remove a character if the caret
// position isn't zero.
if (caretPos > 0) {
text.deleteCharAt(--caretPos);
}
e.consume();
}
// If DELETE is pressed we remove the character at the caret
// position.
else if (e.getCode().equals(KeyCode.DELETE)) {
// DELETE should only remove a character if the caret isn't
// positioned after that last character in the text.
if (caretPos < text.length()) {
text.deleteCharAt(caretPos);
}
}
// If LEFT key is pressed we move the caret one step to the left.
else if (e.getCode().equals(KeyCode.LEFT)) {
caretPos--;
}
// If RIGHT key is pressed we move the caret one step to the right.
else if (e.getCode().equals(KeyCode.RIGHT)) {
caretPos++;
}
// Otherwise we just add the key text to the text.
// TODO We are currently not handling UP/DOWN keys (should move
// caret to the end/beginning of the text).
// TODO We are currently not handling keys that doesn't represent
// any symbol,like ALT. Since they don't have a text,they will
// just move the caret one step to the right. In this case,that
// caret should just hold its current position.
else {
text.insert(caretPos++,e.getText());
e.consume();
}
final int finalPos = caretPos;
// We set the editor text to the new text and finally we move the
// caret to its new position.
editor.setText(text.toString());
Platform.runLater(() -> editor.positionCaret(finalPos));
});
// We just consume KEY_RELEASED and KEY_TYPED since we don't want to
// have duplicated input.
cb.getEditor().addEventFilter(KeyEvent.KEY_RELEASED,e -> {
e.consume();
});
cb.getEditor().addEventFilter(KeyEvent.KEY_TYPED,e -> {
e.consume();
});
可悲的是,这也没有解决问题.如果我选择“Three is a number”项,然后尝试删除“Three”中的最后一个“e”,这是text属性将在之间切换的值:
TextProperty: Three is a number
TextPropery: Thre is a number
TextPropery:
所以它首先删除了正确的字符,但是由于某种原因它删除了整个字符串.如前所述,这只是因为谓词已经设置,而且只有在我第一次选择项目后进行第一次输入时才会发生这种情况.
最佳答案
了Jonatan,
正如Manuel所说,一个问题是setPredicate()会在你更改组合框模型时触发你的changed()方法两次,但真正的问题是组合框会用适合的任何值覆盖编辑器值.以下是您症状的解释:
If I select an item from the list,and then try to remove the last
character in the textfield,nothing happens.
在这种情况下,最后一个char的删除实际上正在发生,但是第一次调用setPredicate()会匹配一个可能的项目(与删除最后一个char的项目完全相同)并将组合框内容更改为仅一个项目.这会导致调用,其中组合框使用当前的combobox.getValue()字符串恢复编辑器值,从而产生没有任何反应的错觉.它还会导致第二次调用您的changed()方法,但此时编辑器文本已经更改.
Why do this only happen the first time,but then never again?
好问题!这只发生一次,因为您正在修改组合框的整个基础模型一次(如前所述,触发对changed()方法的第二次调用).
(编辑:安卓应用网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|