Заполнение текстового поля автозаполнения JavaFX ControlsFX, приводящее к дублированию содержимогоJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Заполнение текстового поля автозаполнения JavaFX ControlsFX, приводящее к дублированию содержимого

Сообщение Anonymous »

Я использовал JavaFX ControlsFX TextFields.bindAutoCompletion() с асинхронными задачами javafx, чтобы заполнить результаты автозаполнения из моей базы данных neo4j после того, как пользователь вводит два символа. Проблема в том, что если пользователь очищает текстовое поле и вводит новые значения для поиска, теперь есть две привязки, поэтому отображаются два всплывающих окна автозаполнения.
Изображение

Мне нужно иметь возможность полностью отвязать текстовое поле от старого списка и привязать его автозаполнение к новый список. Кажется, абстрактный метод, который я использую, dispose() ничего не делает в стандартном классе AutoCompletionBinding?

Код: Выделить всё

    AutoCompletionBinding clientBinding;
private void getClientAutoComplete(TextField clientNameTextField) {
String input = clientNameTextField.getText().toUpperCase();
if (input.length() < 2  && clientBinding != null) {
clientBinding.dispose();
} else if (input.length() == 2) {
var queryTask = SimpleCypher.getClientAutoComplete(input);

queryTask.setOnSucceeded(event -> {
AutoCompletionBinding clientBinding = TextFields.bindAutoCompletion(clientNameTextField, queryTask.getValue());
clientBinding.setOnAutoCompleted(e -> getClientData(e.getCompletion().getId()));
});

// Start the task asynchronously
Thread queryThread = new Thread(queryTask);
queryThread.setDaemon(true); // Set as daemon thread to allow application exit
queryThread.start();
}
}
Вот задача Javafx:

Код: Выделить всё

    public static Task[*]> getClientAutoComplete(String input){
Task task = new Task() {
@Override
protected List call() throws Exception {
List resultClients = new ArrayList();
try (Session session = DatabaseConnection.getSession()) {
Result result = session.run(
"""
MATCH (n:Client)
WHERE toUpper(n.name) CONTAINS $textFieldInput
RETURN n.id AS id
, n.name AS name
, n.phone AS num
""",
Values.parameters("textFieldInput", input));
while (result.hasNext()) {
Record record = result.next();
resultClients.add(
new Client(
record.get("id").asInt(),
record.get("name").asString(),
record.get("num").isNull() ? null : record.get("num").asString()
));
}
}
return resultClients;
}
};
task.setOnFailed(event -> SimpleCypher.handleQueryError(event));
return task;
}
Я считаю, что решение состоит в том, чтобы создать собственный класс, который переопределяет некоторые абстрактные методы AutoCompletionBinding. Но как мне лучше всего реализовать это на основе того, что мне нужно, а именно возможность для пользователя вводить значение, которое запрашивается в базе данных, а затем заполняет текстовое поле, а также удалять любые предыдущие привязки из предыдущего ввода ?
Вот что у меня есть на данный момент для реализации, но я не уверен, что именно мне нужно вложить в реализацию, чтобы она заработала?:

Код: Выделить всё

import java.util.Collection;

import org.controlsfx.control.textfield.AutoCompletionBinding;

import javafx.scene.Node;
import javafx.util.Callback;
import javafx.util.StringConverter;

public class Neo4jAutoCompletionBinding extends AutoCompletionBinding {

protected Neo4jAutoCompletionBinding(Node completionTarget,
Callback suggestionProvider, StringConverter converter) {
super(completionTarget, suggestionProvider, converter);
// TODO Auto-generated constructor stub
}

@Override
public void dispose() {
// TODO Auto-generated method stub

}

@Override
protected void completeUserInput(T completion) {
// TODO Auto-generated method stub

}

}
  • Я пытался удалить предыдущие привязки автозаполнения каждый раз при запуске нового запроса. Но это не сработало, все привязки остались.
  • Я пробовал привязываться к ObservableList, где ObservableList получал результаты запроса задачи Javafx, но привязка никогда не обновлялась, чтобы показать новые добавленные ценности. Он будет привязан к пустому списку и останется таким, несмотря на то, что ObservableList добавит новые значения из базы данных.
Я ожидаю, что смогу чтобы ввести несколько символов, асинхронно обращайтесь к базе данных, чтобы не зависал пользовательский интерфейс. А затем показывать действительные результаты, одновременно устраняя любую предыдущую привязку, чтобы привязки не накладывались друг на друга и не вызывали путаницу, когда пользователь выполняет автозаполнение и автоматически заполняет неправильное значение, потому что фокус приложения был на другом всплывающем окне привязки, как это может можно увидеть на этом изображении:
Изображение

Обновление: добавление MCVE, чтобы другие могли устранять неполадки и экспериментировать с решениями:
Структура проекта:
Изображение

Код:

Код: Выделить всё

package com.autocomplete.example;

import org.controlsfx.control.textfield.AutoCompletionBinding;
import org.controlsfx.control.textfield.TextFields;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

//Run project using mvn javafx:run
//You can see the bindings coninutally stack on top of eachother by using the ESC key on the keyboard to move the front one out of focus
public class AutocompleteExample extends Application {

private static final ObservableList names1 = FXCollections.observableArrayList(
"Alice", "Adam", "Alfred", "Amon", "Alfredo", "Al", "Albert"
);

private static final ObservableList names2 = FXCollections.observableArrayList(
"Bob", "Conner", "Robin", "Fred", "Freddy", "Edward", "Fredward", "Mariam"
);

@Override
public void start(Stage primaryStage) {
TextField textField = new TextField();

textField.setOnKeyTyped(event -> {
AutoCompletionBinding nameBinding = null;
String input = textField.getText().toUpperCase();
if (input.length() == 2){
if (input.startsWith("A")) {
if (nameBinding != null) nameBinding.dispose();
nameBinding = TextFields.bindAutoCompletion(textField, names1);
nameBinding.setOnAutoCompleted(val -> System.out.println("You selected "+ val.getCompletion() +" from list 1."));
} else {
if (nameBinding != null) nameBinding.dispose();
nameBinding = TextFields.bindAutoCompletion(textField, names2);
nameBinding.setOnAutoCompleted(val -> System.out.println("You selected "+ val.getCompletion() +" from list 2."));
}
} else if (nameBinding != null && input.length() < 2) nameBinding.dispose();
});

VBox root = new VBox(10, textField);
Scene scene = new Scene(root, 300, 200);
primaryStage.setScene(scene);
primaryStage.setTitle("Autocomplete Example");
primaryStage.show();
}

public static void main(String[] args) {
launch(args);
}
ПОМ:

Код: Выделить всё


4.0.0
com.autocomplete.example
AutocompleteExample
1.0-SNAPSHOT

UTF-8
21
21.0.4
com.autocomplete.example.AutocompleteExample



org.openjfx
javafx-controls
${javafx.version}


org.openjfx
javafx-fxml
${javafx.version}


org.openjfx
javafx-base
${javafx.version}



org.neo4j.driver
neo4j-java-driver
5.18.0



org.controlsfx
controlsfx
11.2.0





org.apache.maven.plugins
maven-compiler-plugin
3.8.1

${maven.compiler.release}



org.openjfx
javafx-maven-plugin
0.0.8




default-cli

${exec.mainClass}

--add-exports
javafx.base/com.sun.javafx.event=org.controlsfx.controls
--add-modules=javafx.base








Файл информации о модуле:

Код: Выделить всё

module com.autocomplete.example {
requires javafx.base;
requires javafx.fxml;
requires transitive javafx.controls;
requires transitive javafx.graphics;
requires org.controlsfx.controls;

opens com.autocomplete.example to javafx.fxml;
exports com.autocomplete.example;
}
Изображение


Подробнее здесь: https://stackoverflow.com/questions/790 ... licate-con
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»