2015-08-14 68 views
2

鏈接JavaFX中兩種效應很容易與.setInput()JavaFX的8個連鎖效果

if (isDropShadowEnabled) 
    innerShadow.setInput(dropShadow); 
content.setEffect(innerShadow); 

但我怎麼多重連鎖效應,當這些影響任何一個可能沒有啓用?

說第三個效果是布盧姆。所以我想要一個Dropshadow,InnerShadow和Bloom,但在其他時候只需要一個DropShadow和Bloom,並且不需要InnerShadow。我試圖避免大量'如果',我一直在尋找一些沿着effect.getChildren()。add('很多效果')的東西。但是在谷歌搜索幾個小時後,沒有任何東西可以跳出來。

回答

4

也許你可以使用這段代碼的一些想法。對不起,它有點複雜,我現在沒有時間來解釋它。

s1 s2 s3 s4

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); 
    } 
} 
+0

這將需要一些認真的研究,因此這將是幾個小時,但由於! – Frank

+0

太棒了!這很好。我使用文字而不是圖像,並且還添加了照明。照明問題在於它沒有setInput()方法,因此它不可鏈接。我通過將文本與自身重疊並將鏈接效果應用於底部文本並將照明應用於頂部文本來解決該問題。最終的結果是太棒了。謝謝jewelsea。 – Frank