Skip to content

Instantly share code, notes, and snippets.

@uphy
Created January 4, 2017 06:25
Show Gist options
  • Save uphy/f4b81823c005c7bf783f0336d643a1f3 to your computer and use it in GitHub Desktop.
Save uphy/f4b81823c005c7bf783f0336d643a1f3 to your computer and use it in GitHub Desktop.
How to develop KNIME node with JavaFX
package it.pkg;
import java.awt.BorderLayout;
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.JPanel;
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.NodeDialogPane;
import org.knime.core.node.NodeSettingsRO;
import org.knime.core.node.NodeSettingsWO;
import org.knime.core.node.NotConfigurableException;
import org.knime.core.node.port.PortObjectSpec;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
/**
* Node extension with JavaFX example.
*
* <p>
* To make this class work, you need to append following settings to Knime.ini.
*
* <pre>
* -Dosgi.framework.extensions=org.eclipse.fx.osgi
* -Dorg.osgi.framework.bundle.parent=ext
* </pre>
* </p>
*
* @author uphy.jp
*/
public class JavaFXDialog extends NodeDialogPane {
private TextField count;
protected JavaFXDialog() {
super();
final JPanel panel = new JPanel(new BorderLayout());
final JFXPanel fxpanel = new JFXPanel();
runOnJavaFXThread(() -> {
final VBox vbox = new VBox();
count = new TextField();
vbox.getChildren().add(count);
final Scene scene = new Scene(vbox);
fxpanel.setScene(scene);
Platform.setImplicitExit(false);
});
panel.add(fxpanel, BorderLayout.CENTER);
addTab("Options", panel);
}
@Override
protected void saveSettingsTo(NodeSettingsWO settings) throws InvalidSettingsException {
settings.addInt(TestModel.CFGKEY_COUNT, runOnJavaFXThread(() -> Integer.parseInt(count.getText())));
}
@Override
protected void loadSettingsFrom(NodeSettingsRO settings, PortObjectSpec[] specs) throws NotConfigurableException {
final int countInt = settings.getInt(TestModel.CFGKEY_COUNT, 100);
runOnJavaFXThread(() -> count.setText(String.valueOf(countInt)));
}
private void runOnJavaFXThread(Runnable task) {
runOnJavaFXThread(() -> {
task.run();
return null;
});
}
private <V> V runOnJavaFXThread(Callable<V> task) {
Semaphore s = new Semaphore(0);
AtomicReference<V> ref = new AtomicReference<>();
Platform.runLater(() -> {
try {
V result = task.call();
ref.set(result);
} catch (Throwable e) {
e.printStackTrace();
}
s.release();
});
try {
s.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
return ref.get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment