Java examples for JavaFX:ComboBox
Customizes the JavaFX ComboBox to call the callback until user clicks on the ComboBox or after a delay.
/*// ww w .ja v a2 s .co m * Copyright (c) 2002-2015, JIDE Software Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ //package com.java2s; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.collections.ObservableList; import javafx.concurrent.Task; import javafx.concurrent.WorkerStateEvent; import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.control.ComboBox; import javafx.util.Callback; import javafx.util.Duration; public class Main { private final static String PROPERTY_TASK = "LazyLoadUtils.Task"; /** * Customizes the ComboBox to call the callback until user clicks on the ComboBox or after a delay. * * @param comboBox the ComboBox. * @param callback the callback to create the ObservableList. * @param delay the delay before the callback is called. * @param beforeShowing whether to trigger the callback before the ComboBox popup is about to show, if the callback * hasn't called yet. * @param initialValue the initial value. Null if the value has been set on the ComboBox. * @param <T> The type of the value that has been selected or otherwise entered in to this ComboBox. */ protected static <T> void customizeComboBox(ComboBox<T> comboBox, Callback<ComboBox<T>, ObservableList<T>> callback, Duration delay, boolean beforeShowing, T initialValue) { Task oldTask = getTask(comboBox); if (oldTask != null) { oldTask.cancel(true); } if (initialValue != null) comboBox.setValue(initialValue); Task<ObservableList<T>> task = new Task<ObservableList<T>>() { @Override protected ObservableList<T> call() throws Exception { return callback.call(comboBox); } }; task.setOnSucceeded(new EventHandler<WorkerStateEvent>() { @Override public void handle(WorkerStateEvent event) { T item = comboBox.getValue(); Object value = event.getSource().getValue(); if (value instanceof ObservableList) { //noinspection unchecked comboBox.setItems((ObservableList<T>) value); //noinspection unchecked if (item == null || !((ObservableList<T>) value).contains(item)) { comboBox.setValue(null); comboBox.getSelectionModel().select(0); } else { // trick in order to show the item. should be a bug in JavaFX combobox comboBox.setValue(null); comboBox.setValue(item); } } } }); // when user clicks on the combobox, we will retrieve the fonts, not using thread because we don't want the empty // list to show up. User has to wait for a while if the task takes a long time if (beforeShowing) { comboBox.setOnShowing(new EventHandler<Event>() { @Override public void handle(Event event) { if (!task.isRunning() && !task.isDone()) { task.run(); } comboBox.setOnShowing(null); } }); } // or use Timeline to get the font in a thread after 1 second, if user didn't click on the font combobox before that startTimer(delay, task); putTask(comboBox, task); } private static Task getTask(Node node) { Object task = node.getProperties().get(PROPERTY_TASK); if (task instanceof Task) { return (Task) task; } else { return null; } } private static <T> void startTimer(Duration delay, Task<ObservableList<T>> task) { if (delay != null && !delay.isIndefinite()) { Timeline timeline = new Timeline(); timeline.getKeyFrames().add( new KeyFrame(delay, new EventHandler<ActionEvent>() { public void handle(ActionEvent t) { if (!task.isRunning() && !task.isDone()) { new Thread(task).start(); } } })); timeline.play(); } } private static void putTask(Node node, Task task) { node.getProperties().put(PROPERTY_TASK, task); } }