2014-12-11 16 views
24

javafx'te önceden tanımlanmış birkaç etkinlik sınıfı vardır. Event.ANY, KeyEvent.KEY_TYPED, MouseEvent.ANY vb. Olaylar için gelişmiş filtreleme ve taşıma sistemi de bulunmaktadır. Ve bazı özel sinyaller göndermek için yeniden kullanmak istiyorum.Özel etkinlikler nasıl yayılır ve işlenir?

Özel olay türü CustomEvent.Any'yi nasıl oluşturabilirim, bu olayı program aracılığıyla yayabilir ve bir düğümde kullanabilir miyim? Genel olarak

cevap

29

:

  1. arzu edilen bir EventType oluşturun.
  2. İlgili Event'u oluşturun.
  3. Node.fireEvent() numaralı telefonu arayın. İlgili Etkinlik Türleri için Handlers ve/veya Filters ekleyin.

Bazı açıklamalar:

EventType<MyEvent> OPTIONS_ALL = new EventType<>("OPTIONS_ALL"); 
: EventTypes tüm kök olacaktır

Eğer bir olay basamaklarını oluşturmak içeren "Tümü" veya "Herhangi biri" türüyle başlamak istiyorsanız,

Bu, bu tür kökenini oluşturmak mümkün kılar:

EventType<MyEvent> BEFORE_STORE = new EventType<>(OPTIONS_ALL, "BEFORE_STORE"); 

sonra hangiuzanmaktadır (MyEvent sınıf yazmak). EventTypes bu olay sınıfına yazılmalıdır (örneğim gibi).

Şimdi kullanın (ya da başka bir deyişle: Yangın) olay:

Event myEvent = new MyEvent(); 
Node node = ....; 
node.fireEvent(myEvent); 

Bu etkinliği yakalamak istiyorsanız: Burada

Node node = ....; 
node.addEventHandler(OPTIONS_ALL, event -> handle(...)); 
node.addEventHandler(BEFORE_STORE, event -> handle(...)); 
16

(biraz aşırı karmaşık) örnek uygulaması eckig'in (mükemmel) cevabında ana hatlarını çizen bazı kavramları göstermek.

Örnek, reaktör düğümlerinin döşemeli bir bölmesi olan görsel bir alan oluşturur. Özel bir yıldırım olayı periyodik olarak rastgele bir düğüme gönderilir, bu da etkinliği aldığında sarı renkte yanıp söner. Filtreler ve işleyicileri ana alana eklenir ve sisteme aktarılması bildirilir, böylece olayın köpürme ve yakalama aşamalarını görebilirsiniz.

LightningEvent'in kendisinin kodu temel olarak doğrudan JavaFX kaynağındaki standart ActionEvent kodundan kopyalandı, olay kodunuz muhtemelen biraz daha basit olabilir.

enter image description here

import javafx.animation.*; 
import javafx.application.Application; 
import javafx.event.*; 
import javafx.scene.Scene; 
import javafx.scene.layout.TilePane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Rectangle; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

import java.util.Random; 

public class LightningSimulator extends Application { 
    private static final int FIELD_SIZE = 10; 

    private static final Random random = new Random(42); 

    @Override 
    public void start(Stage stage) throws Exception { 
     TilePane field = generateField(); 

     Scene scene = new Scene(field); 
     stage.setScene(scene); 
     stage.setResizable(false); 
     stage.show(); 

     field.addEventFilter(
       LightningEvent.PLASMA_STRIKE, 
       event -> System.out.println(
         "Field filtered strike: " + event.getI() + ", " + event.getJ() 
       ) 
     ); 

     field.addEventHandler(
       LightningEvent.PLASMA_STRIKE, 
       event -> System.out.println(
         "Field handled strike: " + event.getI() + ", " + event.getJ() 
       ) 
     ); 

     periodicallyStrikeRandomNodes(field); 
    } 

    private void periodicallyStrikeRandomNodes(TilePane field) { 
     Timeline timeline = new Timeline(
       new KeyFrame(
         Duration.seconds(0), 
         event -> strikeRandomNode(field) 
       ), 
       new KeyFrame(
         Duration.seconds(2) 
       ) 
     ); 

     timeline.setCycleCount(Timeline.INDEFINITE); 
     timeline.play(); 
    } 

    private void strikeRandomNode(TilePane field) { 
     LightningReactor struckNode = (LightningReactor) 
       field.getChildren() 
         .get(
           random.nextInt(
             FIELD_SIZE * FIELD_SIZE 
           ) 
         ); 
     LightningEvent lightningStrike = new LightningEvent(
       this, 
       struckNode 
     ); 

     struckNode.fireEvent(lightningStrike); 
    } 

    private TilePane generateField() { 
     TilePane field = new TilePane(); 
     field.setPrefColumns(10); 
     field.setMinWidth(TilePane.USE_PREF_SIZE); 
     field.setMaxWidth(TilePane.USE_PREF_SIZE); 

     for (int i = 0; i < 10; i++) { 
      for (int j = 0; j < 10; j++) { 
       field.getChildren().add(
         new LightningReactor(
           i, j, 
           new StrikeEventHandler() 
         ) 
       ); 
      } 
     } 
     return field; 
    } 

    private class LightningReactor extends Rectangle { 
     private static final int SIZE = 20; 
     private final int i; 
     private final int j; 

     private FillTransition fillTransition = new FillTransition(Duration.seconds(4)); 

     public LightningReactor(int i, int j, EventHandler<? super LightningEvent> lightningEventHandler) { 
      super(SIZE, SIZE); 

      this.i = i; 
      this.j = j; 

      Color baseColor = 
        (i + j) % 2 == 0 
          ? Color.RED 
          : Color.WHITE; 
      setFill(baseColor); 

      fillTransition.setFromValue(Color.YELLOW); 
      fillTransition.setToValue(baseColor); 
      fillTransition.setShape(this); 

      addEventHandler(
        LightningEvent.PLASMA_STRIKE, 
        lightningEventHandler 
      ); 
     } 

     public void strike() { 
      fillTransition.playFromStart(); 
     } 

     public int getI() { 
      return i; 
     } 

     public int getJ() { 
      return j; 
     } 
    } 

    private class StrikeEventHandler implements EventHandler<LightningEvent> { 
     @Override 
     public void handle(LightningEvent event) { 
      LightningReactor reactor = (LightningReactor) event.getTarget(); 
      reactor.strike(); 

      System.out.println("Reactor received strike: " + reactor.getI() + ", " + reactor.getJ()); 


      // event.consume(); if event is consumed the handler for the parent node will not be invoked. 
     } 
    } 

    static class LightningEvent extends Event { 

     private static final long serialVersionUID = 20121107L; 

     private int i, j; 

     public int getI() { 
      return i; 
     } 

     public int getJ() { 
      return j; 
     } 

     /** 
     * The only valid EventType for the CustomEvent. 
     */ 
     public static final EventType<LightningEvent> PLASMA_STRIKE = 
       new EventType<>(Event.ANY, "PLASMA_STRIKE"); 

     /** 
     * Creates a new {@code LightningEvent} with an event type of {@code PLASMA_STRIKE}. 
     * The source and target of the event is set to {@code NULL_SOURCE_TARGET}. 
     */ 
     public LightningEvent() { 
      super(PLASMA_STRIKE); 
     } 

     /** 
     * Construct a new {@code LightningEvent} with the specified event source and target. 
     * If the source or target is set to {@code null}, it is replaced by the 
     * {@code NULL_SOURCE_TARGET} value. All LightningEvents have their type set to 
     * {@code PLASMA_STRIKE}. 
     * 
     * @param source the event source which sent the event 
     * @param target the event target to associate with the event 
     */ 
     public LightningEvent(Object source, EventTarget target) { 
      super(source, target, PLASMA_STRIKE); 

      this.i = ((LightningReactor) target).getI(); 
      this.j = ((LightningReactor) target).getJ(); 
     } 

     @Override 
     public LightningEvent copyFor(Object newSource, EventTarget newTarget) { 
      return (LightningEvent) super.copyFor(newSource, newTarget); 
     } 

     @Override 
     public EventType<? extends LightningEvent> getEventType() { 
      return (EventType<? extends LightningEvent>) super.getEventType(); 
     } 

    } 

} 
İlgili konular