2016-11-15 2 views
0

В моем редактируемом ComboBox, который фильтрует мои предложения из-за ввода, я могу запустить Button событий. Проблема в том, что если я набираю одно из имен моих элементов (например, action3) в редактируемом поле и нажимаю на первое предложение (которое также будет action3), которое является подходящим элементом, оно всегда запускает ButtonEvent с первым индексом action1, потому что он имеет первый индекс, но первый индекс - action1.Link filter Combobox Элемент для ввода

List<EventHandler<ActionEvent>> handlers = Arrays.asList(
      this::action1, 
      this::action2, 
      this::action3 
      ); 

Как я могу связать как действие1 с моим предложением правильное предложение?

public void onEnter(ActionEvent event){ 
    int index = editableComboBox.getSelectionModel().getSelectedIndex(); 
    if (index >= 0) { 
     handlers.get(index).handle(event); 
    } 

} 

EDIT 1:

Мой новый Initialize() Метод выглядит следующим образом:

protected void initialize() { 
    new AutoCompleteBox<>(autoBox);  
    ObservableList<ActionEventHandler> data = FXCollections.observableArrayList(
      new ActionEventHandler("action1", this::action1), 
      new ActionEventHandler("action2", this::action2, 
      new ActionEventHandler("action3", this::action3) 
    ); 
    autoBox.getItems().setAll(data); 
    FilteredList<ActionEventHandler> filtered = new FilteredList<>(data); 
    ComboBox<ActionEventHandler> autoBox = new ComboBox<>(filtered); 
    autoBox.setOnAction(event -> { 
     ActionEventHandler h = autoBox.getValue(); 
     if (h != null) { 
      h.handle(event); 
     } 
    }); 
    autoBox.setEditable(true); 
    autoBox.setConverter(new StringConverter<ActionEventHandler>() { 

     @Override 
     public String toString(ActionEventHandler object) { 
      return object == null ? "" : object.toString(); 
     } 

     @Override 
     public ActionEventHandler fromString(String string) { 
      if (string == null) { 
       return null; 
      } 
      for (ActionEventHandler h : data) { 
       if (string.equals(h.toString())) { 
        return h; 
       } 
      } 
      return null; 
     } 

    }); 

    autoBox.getEditor().textProperty().addListener((observable, oldValue, newValue) -> { 
     filtered.setPredicate(h -> h.toString().startsWith(newValue)); 
    }); 

} 

И обычай ComboBox класс:

public class AutoCompleteBox<T> implements EventHandler<KeyEvent> { 

    private ComboBox comboBox; 
    private StringBuilder sb; 
    private ObservableList<T> data; 
    private boolean moveCaretToPos = false; 
    private int caretPos; 

    public AutoCompleteBox(final ComboBox comboBox) { 
     this.comboBox = comboBox; 
     sb = new StringBuilder();  
     data = comboBox.getItems(); 



     this.comboBox.setEditable(true); 
     this.comboBox.setOnKeyPressed(new EventHandler<KeyEvent>() { 

      @Override 
      public void handle(KeyEvent t) { 
       comboBox.hide(); 
      } 
     }); 
     this.comboBox.setOnKeyReleased(AutoCompleteBox.this); 
    } 

    @Override 
    public void handle(KeyEvent event) { 

     if(event.getCode() == KeyCode.UP) { 
      caretPos = -1; 
      moveCaret(comboBox.getEditor().getText().length()); 
      return; 
     } else if(event.getCode() == KeyCode.DOWN) { 
      if(!comboBox.isShowing()) { 
       comboBox.show(); 
      } 
      caretPos = -1; 
      moveCaret(comboBox.getEditor().getText().length()); 
      return; 
     } else if(event.getCode() == KeyCode.BACK_SPACE) { 
      moveCaretToPos = true; 
      caretPos = comboBox.getEditor().getCaretPosition(); 
     } else if(event.getCode() == KeyCode.DELETE) { 
      moveCaretToPos = true; 
      caretPos = comboBox.getEditor().getCaretPosition(); 
     } 

     if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT 
       || event.isControlDown() || event.getCode() == KeyCode.HOME 
       || event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) { 
      return; 
     } 

     ObservableList list = FXCollections.observableArrayList(); 
     for (int i=0; i<data.size(); i++) { 
      if(data.get(i).toString().toLowerCase().startsWith(
        AutoCompleteBox.this.comboBox 
       .getEditor().getText().toLowerCase())) { 
       list.add(data.get(i)); 
      } 
     } 
     String t = comboBox.getEditor().getText(); 

     comboBox.setItems(list); 
     comboBox.getEditor().setText(t); 
     if(!moveCaretToPos) { 
      caretPos = -1; 
     } 
     moveCaret(t.length()); 
     if(!list.isEmpty()) { 
      comboBox.show(); 
     } 
    } 

    private void moveCaret(int textLength) { 
     if(caretPos == -1) { 
      comboBox.getEditor().positionCaret(textLength); 
     } else { 
      comboBox.getEditor().positionCaret(caretPos); 
     } 
     moveCaretToPos = false; 
    } 
} 

я не могу свяжите функции (например, action1 Строка action1), или что я верю больше, я не могу объединить пользовательский класс с моим настраиваемым ComboBox.

ответ

2

В этом случае, кажется, лучше всего использовать EventHandler<ActionEvent> S в качестве элементов, которые возвращают строки для toString. Добавьте converter, чтобы преобразовать объект в объект не String.

public class ActionEventHandler implements EventHandler<ActionEvent> { 

    private final EventHandler<ActionEvent> eventHandler; 
    private final String name; 

    public ActionEventHandler(String name, EventHandler<ActionEvent> eventHandler) { 
     Objects.requireNonNull(name); 
     Objects.requireNonNull(eventHandler); 
     this.name = name; 
     this.eventHandler = eventHandler; 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 

    @Override 
    public void handle(ActionEvent event) { 
     eventHandler.handle(event); 
    } 

} 
ObservableList<ActionEventHandler> data = FXCollections.observableArrayList(
     new ActionEventHandler("action1", this::action1), 
     new ActionEventHandler("action2", this::action2), 
     new ActionEventHandler("action3", this::action3) 
); 
FilteredList<ActionEventHandler> filtered = new FilteredList<>(data); 
ComboBox<ActionEventHandler> comboBox = new ComboBox<>(filtered); 
comboBox.setOnAction(event -> { 
    ActionEventHandler h = comboBox.getValue(); 
    if (h != null) { 
     h.handle(event); 
    } 
}); 
comboBox.setEditable(true); 
comboBox.setConverter(new StringConverter<ActionEventHandler>() { 

    @Override 
    public String toString(ActionEventHandler object) { 
     return object == null ? "" : object.toString(); 
    } 

    @Override 
    public ActionEventHandler fromString(String string) { 
     if (string == null) { 
      return null; 
     } 
     for (ActionEventHandler h : data) { 
      if (string.equals(h.toString())) { 
       return h; 
      } 
     } 
     return null; 
    } 

}); 
comboBox.getEditor().textProperty().addListener((observable, oldValue, newValue) -> { 
    filtered.setPredicate(h -> h.toString().startsWith(newValue)); 
}); 

Редактировать

Следующий код должен работать вместе с вашим AutoCompleteBox класса.

@FXML 
private ComboBox<ActionEventHandler> autoBox; 

@FXML 
private void initialize() { 
    autoBox.getItems().setAll(
      new ActionEventHandler("action1", this::action1), 
      new ActionEventHandler("action2", this::action2), 
      new ActionEventHandler("action3", this::action3)); 
    autoBox.setOnAction(event -> { 
     ActionEventHandler h = autoBox.getValue(); 
     if (h != null) { 
      h.handle(event); 
     } 
    }); 
    autoBox.setConverter(new StringConverter<ActionEventHandler>() { 

     @Override 
     public String toString(ActionEventHandler object) { 
      return object == null ? "" : object.toString(); 
     } 

     @Override 
     public ActionEventHandler fromString(String string) { 
      if (string == null) { 
       return null; 
      } 
      for (ActionEventHandler h : autoBox.getItems()) { 
       if (string.equals(h.toString())) { 
        return h; 
       } 
      } 
      return null; 
     } 

    }); 
    new AutoCompleteBox<>(autoBox); 
} 

(я не проверил детали вашего AutoCompleteBox класса, хотя ...)

+0

Я создал собственный ComboBox в новом классе 'AutoCompleteBox <> (autoBox);' который уже доступен для редактирования, я могу добавить ваш нижний код в мои инициализации Controller() '' '' и просто вызвать 'new AutoCompleteBox <> (autoBox); 'потом? Я получаю пустой раскрывающийся список. – Flippy

+0

@Flippy удаляет создание combobox из моего нижнего кода, добавляет его в метод 'initialize()' контроллера и использует 'comboBox.getItems(). SetAll (...)' вместо указания списка элементов в ' ComboBox'. (IDK, если вам нужно изменить свой код с помощью своего типа 'ComboBox' ...) И, конечно же, замените' comboBox' на имя поля 'ComboBox', которое вы используете. – fabian

+0

Я редактирую код в своем вопросе выше, прямо сейчас я получаю элементы (action1 ..), но я не могу использовать действия. – Flippy

0

попытайтесь получить строку элемента и проверить содержимое строки. если его «action3» вы вызываете событие для action3. Код: (String) cbKategorieMain.getSelectedItem() поможет вам содержимое выпадающего списка в качестве строки

+0

Я думаю, больше об обновлении номера индекса к представленным предложениям. – Flippy