У меня есть этот код, который сохраняет размер ширины TableView's TableColumn в качестве предпочтения:
column.widthProperty().addListener((obs, oldWidth, newWidth) -> {
setTablePreference().saveColumnWidthSetting(newWidth.doubleValue(), column.getId().concat(columnWidthSettingsCommons.toString()));
});
Код работает так, как ожидалось (каждый раз, когда изменяется ширина tableColumn, он автоматически сохраняется), но есть возможности для улучшения. При изменении размера tableColumn этот код выполняется сотни раз из-за поведения прослушивателя, который должен прослушивать любое изменение ширины tableColumn.
Исходя из этого, мне было интересно, есть ли способ запустить этот код только один раз, сразу после того, как прослушиватель перестанет работать.
Я думал об использовании отдельного потока, но он создает сотни потоков, а это далеко не то, чего я пытаюсь достичь (это производительность):
column.widthProperty().addListener((obs, oldWidth, newWidth) -> {
new Thread(new Task<>() {
@Override
protected Object call() {
setTablePreference().saveColumnWidthSetting(newWidth.doubleValue(), column.getId().concat(columnWidthSettingsCommons.toString()));
return null;
}
}).start();
});
Итак, мой вопрос: есть ли способ запустить код после того, как прослушиватель перестал прослушивать новые значения?
Создайте Минимальный воспроизводимый пример.
Вы можете использовать PauseTransition, чтобы сохранить изменения только в том случае, если после некоторой паузы дальнейших изменений не произошло. Но, как описано в ответе ниже, это просто не способ сохранить изменения предпочтений; вообще нет необходимости сохранять их только потому, что пользователь их изменил.
В настройках «Обычное завершение работы виртуальной машины Java не приведет к потере ожидающих обновлений…»
@trashgod не может использовать эту библиотеку, как я могу гарантировать, что пользователь, входящий в систему с другого компьютера, будет иметь там свои настройки? Мне пришлось разработать собственное решение для этого
@ SedJ601 SedJ601 Я не понимаю, насколько полезным может быть больше MRE, чем указано. Не могли бы вы пояснить свой комментарий?
@James_D очень хорошее предложение с PauseTransition, возможно, это то, что я искал. Что касается сохранения ширины столбца, на самом деле это очень актуально с точки зрения качества обслуживания клиентов. Простой сценарий: у кого-то есть старый 13-дюймовый ноутбук, поэтому доступная площадь экрана становится потенциальной проблемой. Каждый раз, когда пользователь загружает tableView, ему всегда приходится увеличивать/уменьшать ширину таблицы, чтобы сделать информацию более «читабельной» (что потенциально может привести к тому, что пользователь просто откажется от платформы). Было бы здорово сделать это один раз, не так ли?!
@James_D эта функция будет доступна в следующей версии (доступной к концу следующей недели), приглашаю вас ее проверить! jdeploy.com/gh/FelipeAumannRS/Nume
@FARS, похоже, ты прав.
Ты не понял меня. Вопрос не в том, нужно ли сохранять ширину столбца. Вопрос в том, нужно ли сохранять его каждый раз, когда пользователь меняет его. Почему бы просто не сохранить его, когда пользователь закроет окно (или каким-то образом скроет таблицу)?
Трудно понять, как можно жаловаться на то, что ответивший на вопрос не полностью понял ваш сценарий и что вам не нужен минимальный воспроизводимый пример. Весь смысл мре в том, чтобы полностью прояснить вопрос.




Основное решение состоит в том, чтобы иметь в вашем приложении точки, которые сохраняют настройки (например, закрытие приложения) и позволяют запрашивать последние значения ширины столбцов. На самом деле это обычный поток управления, а не тот стиль внедрения управления/зависимостей, который вы используете. Вы все равно можете отделить настройки от TableView.
Схематично:
public class MyPrefsWriter {
public final Map<String, Producer<String>> props = new LinkedHashMap<>():
public void savePrefs() {
props.forEach((k, v) -> savePreference(k, v.get());
}
}
public class MyPrefsReader { ... }
// Init:
MyPrefsWriter myPrefs = new MyPrefsWriter();
// GUI constructions:
myPrefs.props.put("columnXWidth", () -> columnX.width.toString());
...
// On exit:
myPrefs.savePrefs();
Что касается TableView, вы можете получить всю ширину в одном фрагменте кода, это может быть лучше и компактнее (saveTableViewToPrefs, loadTableViewFromPrefs).
Спасибо за ответ, но я действительно не получаю таких голосов. В моем сценарии это просто неприемлемый подход: в моих приложениях есть десятки tableView (но при необходимости пользователь может создать тысячи из них). Эти tableView разделены по модулям (каждый модуль работает индивидуально, что-то вроде приложения). Эти модули можно закрыть (чтобы позволить приложению освободить немного памяти и процессора), поэтому я не могу просто сохранять настройки во время закрытия приложения.
Кстати, никто об этом не упоминает, но использование настроек из java.util и запись настроек только при закрытии приложения имеет огромный недостаток: информация может не сохраняться в сценариях, когда процесс приложения завершается, компьютер непредсказуемо выключается и т. д.
@FARS Общий совет в этом ответе — сохранять настройки в определенных точках потока вашего приложения. Одним из таких моментов (приведенных в качестве примера в этом ответе) является закрытие приложения. В вашем случае другим моментом будет закрытие «модуля». Что касается упомянутого вами недостатка, предпочтения обычно не считаются важными данными. Но если вы хотите обеспечить сохранение предпочтений пользователя практически в реальном времени, то подход с задержкой, описанный James_D, вероятно, подойдет вам лучше всего.
@Slaw Я согласен, я уже разрабатываю реализацию на основе его подхода.
Следуя предложению @James_D, я разработал реализацию с использованием PauseTransition:
final PauseTransition columnWidthPropertyPauseTransition = new PauseTransition(Duration.seconds(0.5));
column.widthProperty().addListener((obs, oldWidth, newWidth) -> {
adjustNodePosition(tableView);
if (columnWidthPropertyPauseTransition.getStatus() != Animation.Status.RUNNING)
columnWidthPropertyPauseTransition.play();
columnWidthPropertyPauseTransition.setOnFinished(e -> setTablePreference().saveColumnWidthSetting(newWidth.doubleValue(), column.getId().concat(columnWidthSettingsCommons.toString())));
});
Также рассмотрите java.util.prefs.Preferences , рассмотренную здесь.