也許你可以使用這段代碼的一些想法。對不起,它有點複雜,我現在沒有時間來解釋它。
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class Effector extends Application{
@Override
public void start(Stage stage) throws Exception {
ImageView imageView = new ImageView(
new Image(
"http://icons.iconarchive.com/icons/designbolts/smurfs-movie/128/smurfette-icon.png"
)
);
VBox effectControls = new VBox(5);
effectControls.setPadding(new Insets(5));
effectControls.getChildren().setAll(
new EffectController(
"Drop Shadow",
new DropShadow()
),
new EffectController(
"Inner Shadow",
new InnerShadow()
),
new EffectController(
"Bloom",
new Bloom()
)
);
EffectPipeline pipeline = new EffectPipeline(
effectControls.getChildren().stream().map(
node -> ((EffectController) node).getChainableEffect()
).toArray(ChainableEffect[]::new)
);
imageView.effectProperty().bind(
pipeline.chainedEffectProperty()
);
VBox layout = new VBox(
5,
effectControls,
imageView
);
layout.setPadding(new Insets(5));
layout.setAlignment(
Pos.CENTER
);
stage.setScene(
new Scene(
layout
)
);
stage.setResizable(false);
stage.show();
}
class EffectController extends CheckBox {
private final ChainableEffect chainableEffect;
public EffectController(
String text,
Effect effect
) {
super(text);
chainableEffect = new ChainableEffect(
effect
);
this.setSelected(!chainableEffect.isDisabled());
this.selectedProperty().addListener(
(observable, oldValue, newValue) -> {
chainableEffect.disabledProperty().set(!newValue);
}
);
}
public ChainableEffect getChainableEffect() {
return chainableEffect;
}
}
class EffectPipeline {
private List<ChainableEffect> effects;
private ReadOnlyObjectWrapper<Effect> chainedEffect = new ReadOnlyObjectWrapper<>();
public EffectPipeline(ChainableEffect... effects) {
this.effects = Arrays.asList(effects);
for (ChainableEffect chainableEffect: effects) {
chainableEffect.disabledProperty().addListener((observable, oldValue, newValue) -> {
refreshChainedEffect();
});
}
refreshChainedEffect();
}
public void refreshChainedEffect() {
ChainableEffect firstEffect = null, lastEffect = null;
for (ChainableEffect nextEffect : effects) {
nextEffect.setInput(null);
if (nextEffect.isDisabled()) {
continue;
}
if (firstEffect == null) {
firstEffect = nextEffect;
lastEffect = firstEffect;
continue;
}
lastEffect.setInput(nextEffect);
lastEffect = nextEffect;
}
chainedEffect.setValue(
firstEffect == null
? null
: firstEffect.getEffect()
);
}
public Effect getChainedEffect() {
return chainedEffect.get();
}
public ReadOnlyObjectProperty<Effect> chainedEffectProperty() {
return chainedEffect.getReadOnlyProperty();
}
}
class ChainableEffect {
private final Effect effect;
private final Method inputMethod;
private final BooleanProperty disabled = new SimpleBooleanProperty(
false
);
public ChainableEffect(Effect effect) {
if (effect == null) {
throw new IllegalArgumentException("Effect for chaining must not be null");
}
this.effect = effect;
try {
inputMethod = effect.getClass().getMethod(
"setInput",
Effect.class
);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Effect for chaining must implement the setInput method", e);
} catch (SecurityException e) {
throw new IllegalStateException("Creating chainable effects requires a reflection capable security environment", e);
}
}
public ChainableEffect setInput(ChainableEffect chainableEffect) {
try {
inputMethod.invoke(
this.getEffect(),
chainableEffect != null
? chainableEffect.getEffect()
: null
);
return this;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Chainable effect does not support access rights for setInput", e);
} catch (InvocationTargetException e) {
throw new IllegalStateException("Unable to set the input for a chainable effect", e);
}
}
public Effect getEffect() {
return effect;
}
public boolean isDisabled() {
return disabled.get();
}
public BooleanProperty disabledProperty() {
return disabled;
}
public void setDisabled(boolean disabled) {
this.disabled.set(disabled);
}
}
public static void main(String[] args) {
launch(args);
}
}
這將需要一些認真的研究,因此這將是幾個小時,但由於! – Frank
太棒了!這很好。我使用文字而不是圖像,並且還添加了照明。照明問題在於它沒有setInput()方法,因此它不可鏈接。我通過將文本與自身重疊並將鏈接效果應用於底部文本並將照明應用於頂部文本來解決該問題。最終的結果是太棒了。謝謝jewelsea。 – Frank