Added better wrapping/threading for jfx
This commit is contained in:
parent
3707b1f4cd
commit
01271e9e5d
|
@ -1,11 +1,13 @@
|
||||||
package dorkbox.util.javafx;
|
package dorkbox.util.javafx;
|
||||||
|
|
||||||
|
import com.sun.javafx.application.PlatformImpl;
|
||||||
import dorkbox.util.JavaFxUtil;
|
import dorkbox.util.JavaFxUtil;
|
||||||
import dorkbox.util.SwingUtil;
|
import dorkbox.util.SwingUtil;
|
||||||
import javafx.animation.Interpolator;
|
import javafx.animation.Interpolator;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
import javafx.animation.KeyValue;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.WritableValue;
|
import javafx.beans.value.WritableValue;
|
||||||
import javafx.embed.swing.JFXPanel;
|
import javafx.embed.swing.JFXPanel;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
@ -20,25 +22,26 @@ import java.lang.reflect.Method;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is necessary, because JavaFX stage is crap on linux.
|
* This class is necessary, because JavaFX stage is crap on linux. This offers sort-of the same functionality, but via swing instead.
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
class StageAsSwingWrapper {
|
class StageViaSwing {
|
||||||
final JFrame frame;
|
final JFrame frame;
|
||||||
final JFXPanel panel;
|
final JFXPanel panel;
|
||||||
|
|
||||||
|
private boolean inNestedEventLoop = false;
|
||||||
final WritableValue<Float> opacityProperty;
|
final WritableValue<Float> opacityProperty;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
|
||||||
static
|
static
|
||||||
StageAsSwingWrapper create() {
|
StageViaSwing create() {
|
||||||
final StageAsSwingWrapper[] returnVal = new StageAsSwingWrapper[1];
|
final StageViaSwing[] returnVal = new StageViaSwing[1];
|
||||||
|
|
||||||
// this MUST happen on the EDT!
|
// this MUST happen on the EDT!
|
||||||
SwingUtil.invokeAndWait(() -> {
|
SwingUtil.invokeAndWait(() -> {
|
||||||
synchronized (returnVal) {
|
synchronized (returnVal) {
|
||||||
returnVal[0] = new StageAsSwingWrapper();
|
returnVal[0] = new StageViaSwing();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,6 +50,9 @@ class StageAsSwingWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Necessary for us to be able to size our frame based on it's content
|
||||||
|
*/
|
||||||
private static Method method;
|
private static Method method;
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
|
@ -55,11 +61,17 @@ class StageAsSwingWrapper {
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure that javafx application thread is started
|
||||||
|
// Note that calling PlatformImpl.startup more than once is OK
|
||||||
|
PlatformImpl.startup(() -> {
|
||||||
|
// No need to do anything here
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
StageAsSwingWrapper() {
|
StageViaSwing() {
|
||||||
frame = new JFrame() {
|
frame = new JFrame() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -110,55 +122,6 @@ class StageAsSwingWrapper {
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// frame.addWindowListener(new WindowAdapter() {
|
|
||||||
// @Override
|
|
||||||
// public
|
|
||||||
// void windowOpened(final WindowEvent e) {
|
|
||||||
// System.err.println("opened");
|
|
||||||
|
|
||||||
// stage.showingProperty().addListener(new ChangeListener<Boolean>() {
|
|
||||||
// @Override
|
|
||||||
// public
|
|
||||||
// void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
|
|
||||||
// if (newValue) {
|
|
||||||
// JavaFxUtil.runLater(() -> {
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// when the mouse enters or leaves, we want to fade in/out the application
|
|
||||||
// Timeline timelineVis = new Timeline();
|
|
||||||
// scene.addEventHandler(MouseEvent.MOUSE_ENTERED, event1 -> {
|
|
||||||
// timelineVis.stop();
|
|
||||||
// timelineVis.getKeyFrames().clear();
|
|
||||||
// timelineVis.getKeyFrames()
|
|
||||||
// .addAll(new KeyFrame(Duration.millis(700),
|
|
||||||
// new KeyValue(stage.opacityProperty(), 1, Interpolator.EASE_OUT)));
|
|
||||||
// timelineVis.play();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// scene.addEventHandler(MouseEvent.MOUSE_EXITED, event1 -> {
|
|
||||||
// timelineVis.stop();
|
|
||||||
// timelineVis.getKeyFrames().clear();
|
|
||||||
// timelineVis.getKeyFrames()
|
|
||||||
// .addAll(new KeyFrame(Duration.millis(700),
|
|
||||||
// new KeyValue(stage.opacityProperty(), .7, Interpolator.EASE_OUT)));
|
|
||||||
// timelineVis.play();
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// timeline.play();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
|
@ -173,23 +136,27 @@ class StageAsSwingWrapper {
|
||||||
|
|
||||||
public
|
public
|
||||||
void close() {
|
void close() {
|
||||||
frame.dispose();
|
SwingUtil.invokeAndWait(() -> frame.dispose());
|
||||||
latch.countDown();
|
if (inNestedEventLoop) {
|
||||||
|
com.sun.javafx.tk.Toolkit.getToolkit().exitNestedEventLoop(this, null);
|
||||||
|
} else {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
void setSize(final double width, final double height) {
|
void setSize(final double width, final double height) {
|
||||||
frame.setSize((int)width, (int)height);
|
SwingUtil.invokeAndWait(() -> frame.setSize((int)width, (int)height));
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
void setResizable(final boolean resizable) {
|
void setResizable(final boolean resizable) {
|
||||||
frame.setResizable(resizable);
|
SwingUtil.invokeAndWait(() -> frame.setResizable(resizable));
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
void setApplicationIcon(final java.awt.Image icon) {
|
void setApplicationIcon(final java.awt.Image icon) {
|
||||||
frame.setIconImage(icon);
|
SwingUtil.invokeAndWait(() -> frame.setIconImage(icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final
|
private final
|
||||||
|
@ -206,20 +173,27 @@ class StageAsSwingWrapper {
|
||||||
|
|
||||||
// Figure out the size of everything. Because JFXPanel DOES NOT do this.
|
// Figure out the size of everything. Because JFXPanel DOES NOT do this.
|
||||||
frame.pack();
|
frame.pack();
|
||||||
|
|
||||||
sizeToScene();
|
|
||||||
frame.setVisible(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// has javafx stuff on it, must not be called on the EDT
|
||||||
|
sizeToScene();
|
||||||
|
|
||||||
|
SwingUtil.invokeAndWait(() -> frame.setVisible(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
void showAndWait() {
|
void showAndWait() {
|
||||||
show();
|
show();
|
||||||
|
|
||||||
try {
|
if (Platform.isFxApplicationThread()) {
|
||||||
latch.await();
|
inNestedEventLoop = true;
|
||||||
} catch (InterruptedException e) {
|
com.sun.javafx.tk.Toolkit.getToolkit().enterNestedEventLoop(this);
|
||||||
e.printStackTrace();
|
} else {
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +205,7 @@ class StageAsSwingWrapper {
|
||||||
|
|
||||||
public
|
public
|
||||||
void setMinSize(final double width, final double height) {
|
void setMinSize(final double width, final double height) {
|
||||||
frame.setMinimumSize(new Dimension((int)width, (int)height));
|
SwingUtil.invokeAndWait(() -> frame.setMinimumSize(new Dimension((int)width, (int)height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
|
@ -248,9 +222,15 @@ class StageAsSwingWrapper {
|
||||||
final Scene scene = panel.getScene();
|
final Scene scene = panel.getScene();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// use reflection. This is lame, but necessary
|
// use reflection. This is lame, but necessary. must be on the jfx thread
|
||||||
method.invoke(scene);
|
method.invoke(scene);
|
||||||
frame.setSize((int)scene.getWidth(), (int)scene.getHeight());
|
|
||||||
|
// must be on the EDT
|
||||||
|
SwingUtil.invokeAndWait(() -> {
|
||||||
|
frame.setSize((int)scene.getWidth(), (int)scene.getHeight());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -259,7 +239,12 @@ class StageAsSwingWrapper {
|
||||||
|
|
||||||
public
|
public
|
||||||
void setScene(final Scene scene) {
|
void setScene(final Scene scene) {
|
||||||
panel.setScene(scene);
|
// must be on the JFX or EDT threads
|
||||||
|
if (!Platform.isFxApplicationThread() || !EventQueue.isDispatchThread()) {
|
||||||
|
JavaFxUtil.invokeAndWait(() -> panel.setScene(scene));
|
||||||
|
} else {
|
||||||
|
panel.setScene(scene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
public
|
|
@ -119,7 +119,7 @@ import java.util.function.Consumer;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class Wizard {
|
public class Wizard {
|
||||||
final StageAsSwingWrapper stage = StageAsSwingWrapper.create();
|
final StageViaSwing stage = StageViaSwing.create();
|
||||||
|
|
||||||
private final Text headerText;
|
private final Text headerText;
|
||||||
private final VBox center;
|
private final VBox center;
|
||||||
|
@ -621,7 +621,7 @@ public class Wizard {
|
||||||
boolean BUTTON_PREV_INIT = false;
|
boolean BUTTON_PREV_INIT = false;
|
||||||
boolean BUTTON_NEXT_INIT = false;
|
boolean BUTTON_NEXT_INIT = false;
|
||||||
|
|
||||||
void updatePage(StageAsSwingWrapper stage, boolean advancing) {
|
void updatePage(StageViaSwing stage, boolean advancing) {
|
||||||
Flow flow = getFlow();
|
Flow flow = getFlow();
|
||||||
if (flow == null) {
|
if (flow == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -686,7 +686,7 @@ public class Wizard {
|
||||||
}
|
}
|
||||||
|
|
||||||
private
|
private
|
||||||
void refreshCurrentPage(final StageAsSwingWrapper stage, final WizardPage currentPage) {
|
void refreshCurrentPage(final StageViaSwing stage, final WizardPage currentPage) {
|
||||||
// put in default actions
|
// put in default actions
|
||||||
if (!BUTTON_PREV_INIT) {
|
if (!BUTTON_PREV_INIT) {
|
||||||
BUTTON_PREV_INIT = true;
|
BUTTON_PREV_INIT = true;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user