2017-01-31 3 views
1

Diese Frage der Code unter eine Geschichte, zu vergleichen javafx: How to add an appropriate listener to an ensemble demo?JavaFX: Wie erzwinge das erneute Rendern eines WriteableImage nach der Größenänderung?

import javafx.application.Application; 
import javafx.beans.Observable; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.event.EventHandler; 
import javafx.geometry.Rectangle2D; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.image.ImageView; 
import javafx.scene.image.PixelWriter; 
import javafx.scene.image.WritableImage; 
import javafx.scene.input.KeyCode; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Screen; 
import javafx.stage.Stage; 

public class ImageOperationApp extends Application 
{ 
private SimpleDoubleProperty gridSize = new SimpleDoubleProperty(3.0); 
private SimpleDoubleProperty hueFactor = new SimpleDoubleProperty(12.0); 
private SimpleDoubleProperty hueOffset = new SimpleDoubleProperty(240.0); 

Rectangle2D scr=Screen.getPrimary().getVisualBounds(); 
int size1 = (int) (scr.getWidth() * 0.62); 
int size2 = (int) (scr.getHeight() * 0.62); 

SimpleIntegerProperty sip1=new SimpleIntegerProperty(888); 
SimpleIntegerProperty sip2=new SimpleIntegerProperty(888); 


private void renderImage(WritableImage img, double gridSize, double hueFactor, double hueOffset) 
{ 
    PixelWriter pw = img.getPixelWriter(); 
    double w = sip1.doubleValue(); 
    double h = sip2.doubleValue(); 
    System.out.println("w "+w+" h "+h);    
    double xRatio = 0.0; 
    double yRatio = 0.0; 
    double hue = 0.0; 

    for (int y = 0; y < h; y++) 
     for (int x = 0; x < w; x++) 
     { 
      xRatio = x/w; 
      yRatio = y/h; 
      hue = Math.sin(yRatio * (gridSize * Math.PI)) * Math.sin(xRatio * (gridSize * Math.PI)) 
        * Math.tan(hueFactor/20.0) * 360.0 + hueOffset; 
      Color c = Color.hsb(hue, 1.0, 1.0); 
      pw.setColor(x, y, c); 
     } 
} 

public Parent createContent() 
{ 
    StackPane root = new StackPane(); 
    WritableImage img = new WritableImage(sip1.get(), sip2.get()); 
    gridSize.addListener((Observable observable) -> { 
     renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
    }); 

    hueFactor.addListener((Observable observable) -> { 
     renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
    }); 
    hueOffset.addListener((Observable observable) -> { 
     renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
    }); 

    sip1.addListener((Observable observable) -> { 
     renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
    }); 

    sip2.addListener((Observable observable) -> { 
     renderImage(img, gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
    });  
    renderImage(img, 3.0, 12.0, 240.0); 
    ImageView view = new ImageView(img); 
    root.getChildren().add(view); 
    return root; 
} 

@Override 
public void start(Stage primaryStage) throws Exception 
{ 
    Scene scene = new Scene(createContent()); 
    scene.setOnKeyPressed(new EventHandler<KeyEvent>() 
    { 
     @Override 
     public void handle(KeyEvent event) 
     { 
      if (event.getCode() == KeyCode.X) 
       gridSize.set(gridSize.get() + 0.5); 
      if (event.getCode() == KeyCode.Y) 
      { 
       double t = gridSize.get(); 
       t -= .5; 
       if (t < 0) 
        t = 0; 
       gridSize.set(t); 
      } 

      if (event.getCode() == KeyCode.V) 
       hueFactor.set(hueFactor.get() + 0.5); 
      if (event.getCode() == KeyCode.C) 
      { 
       double t = hueFactor.get(); 
       t -= .5; 
       if (t < 0) 
        t = 0; 
       hueFactor.set(t); 
      } 

      if (event.getCode() == KeyCode.N) 
       hueOffset.set(hueOffset.get() + 10); 
      if (event.getCode() == KeyCode.B) 
      { 
       double t = hueOffset.get(); 
       t -= 10; 
       if (t < 0) 
        t = 0; 
       hueOffset.set(t); 
      } 

     } 
    }); 


    scene.widthProperty().addListener(new ChangeListener<Number>() { 
     @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneWidth, Number newSceneWidth) { 
      System.out.println("Width: " + newSceneWidth); 
      sip1.set(newSceneWidth.intValue()); 
     } 
    }); 

    scene.heightProperty().addListener(new ChangeListener<Number>() { 
     @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneHeight, Number newSceneHeight) { 
      System.out.println("Height: " + newSceneHeight); 
      sip2.set(newSceneHeight.intValue()); 
     } 
    }); 
    primaryStage.setTitle("JavaFX Demo"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

public static void main(String[] args) 
{ 
    launch(args); 
} 
} 

Um es in sich geschlossene und fahrbare zu machen, ich gepostet die ganze Sache.
Da Sie sich davon überzeugen können, dass die Größenänderungsereignisse von der renderImage() -Methode bemerkt werden, zeigt es jedoch nicht das erwartete Verhalten.
Offensichtlich die for-Schleife nicht alle Pixel, sondern nur ein Teil neu einfärben. Gibt es eine einfache Lösung oder ist ein WriteableImage prinzipiell nicht in der Lage die resize-Events zu bearbeiten?

Antwort

1

Ich habe einige Änderungen am Code vorgenommen:

1) neue Instanz Vars (einschließlich WritableImage):

private static final int IMAGE_MAX_WIDTH = 888; 
private static final int IMAGE_MAX_HEIGHT = 888; 

private final SimpleIntegerProperty sip1 = new SimpleIntegerProperty(IMAGE_MAX_WIDTH); 
private final SimpleIntegerProperty sip2 = new SimpleIntegerProperty(IMAGE_MAX_HEIGHT); 
private WritableImage img = new WritableImage(sip1.get(), sip2.get()); 
private ImageView view; 

2) in renderImage in der ersten Zeile ein neues WritableImage instanziiert und es eingestellt zu view

private void renderImage(double gridSize, double hueFactor, double hueOffset) { 
    img = new WritableImage(sip1.intValue(), sip2.intValue()); 
    view.setImage(img); 
    ..... 
} 

3) in createContent

public Parent createContent() { 
    StackPane root = new StackPane(); 
    img = new WritableImage(sip1.intValue(), sip2.intValue()); 
    view = new ImageView(img); 
    .... 
} 

4) in start fix Ausnahmen:

scene.widthProperty().addListener((observableValue, oldSceneWidth, newSceneWidth) -> { 
    System.out.println("Width: " + newSceneWidth); 
    int newValue = newSceneWidth.intValue(); 
    if (newValue < IMAGE_MAX_WIDTH) { 
     sip1.set(newValue); 
    } 
}); 

scene.heightProperty().addListener((observableValue, oldSceneHeight, newSceneHeight) -> { 
    System.out.println("Height: " + newSceneHeight); 
    int newValue = newSceneHeight.intValue(); 
    if (newValue < IMAGE_MAX_HEIGHT) { 
     sip2.set(newValue); 
    } 
}); 

Wenn ich Ihr Problem richtig verstanden diese Änderungen sollte es beheben.

Gesamte Klasse:

import javafx.application.Application; 
import javafx.beans.Observable; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.event.EventHandler; 
import javafx.geometry.Rectangle2D; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.image.ImageView; 
import javafx.scene.image.PixelWriter; 
import javafx.scene.image.WritableImage; 
import javafx.scene.input.KeyCode; 
import javafx.scene.input.KeyEvent; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Screen; 
import javafx.stage.Stage; 

public class ImageOperationApp extends Application { 
    private SimpleDoubleProperty gridSize = new SimpleDoubleProperty(3.0); 
    private SimpleDoubleProperty hueFactor = new SimpleDoubleProperty(12.0); 
    private SimpleDoubleProperty hueOffset = new SimpleDoubleProperty(240.0); 

    Rectangle2D scr = Screen.getPrimary().getVisualBounds(); 
    int size1 = (int) (scr.getWidth() * 0.62); 
    int size2 = (int) (scr.getHeight() * 0.62); 

    private static final int IMAGE_MAX_WIDTH = 888; 
    private static final int IMAGE_MAX_HEIGHT = 888; 

    private final SimpleIntegerProperty sip1 = new SimpleIntegerProperty(IMAGE_MAX_WIDTH); 
    private final SimpleIntegerProperty sip2 = new SimpleIntegerProperty(IMAGE_MAX_HEIGHT); 
    private WritableImage img = new WritableImage(sip1.get(), sip2.get()); 
    private ImageView view; 
    private void renderImage(double gridSize, double hueFactor, double hueOffset) { 
     img = new WritableImage(sip1.get(), sip2.get()); 
     view.setImage(img); 
     PixelWriter pw = img.getPixelWriter(); 
     double w = sip1.doubleValue(); 
     double h = sip2.doubleValue(); 
     System.out.println("w " + w + " h " + h); 
     double xRatio = 0.0; 
     double yRatio = 0.0; 
     double hue = 0.0; 

     for (int y = 0; y < h; y++) 
      for (int x = 0; x < w; x++) { 
       xRatio = x/w; 
       yRatio = y/h; 
       hue = Math.sin(yRatio * (gridSize * Math.PI)) * Math.sin(xRatio * (gridSize * Math.PI)) 
         * Math.tan(hueFactor/20.0) * 360.0 + hueOffset; 
       Color c = Color.hsb(hue, 1.0, 1.0); 
       pw.setColor(x, y, c); 
      } 
    } 

    public Parent createContent() { 
     StackPane root = new StackPane(); 
     img = new WritableImage(sip1.intValue(), sip2.intValue()); 
     view = new ImageView(img); 

     gridSize.addListener((Observable observable) -> { 
      renderImage(gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
     }); 

     hueFactor.addListener((Observable observable) -> { 
      renderImage(gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
     }); 
     hueOffset.addListener((Observable observable) -> { 
      renderImage(gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
     }); 

     sip1.addListener((Observable observable) -> { 
      renderImage(gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
     }); 

     sip2.addListener((Observable observable) -> { 
      renderImage(gridSize.doubleValue(), hueFactor.doubleValue(), hueOffset.doubleValue()); 
     }); 

     renderImage(3.0, 12.0, 240.0); 
     root.getChildren().add(view); 
     return root; 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     Scene scene = new Scene(createContent()); 
     scene.setOnKeyPressed(new EventHandler<KeyEvent>() { 
      @Override 
      public void handle(KeyEvent event) { 
       if (event.getCode() == KeyCode.X) 
        gridSize.set(gridSize.get() + 0.5); 
       if (event.getCode() == KeyCode.Y) { 
        double t = gridSize.get(); 
        t -= .5; 
        if (t < 0) 
         t = 0; 
        gridSize.set(t); 
       } 

       if (event.getCode() == KeyCode.V) 
        hueFactor.set(hueFactor.get() + 0.5); 
       if (event.getCode() == KeyCode.C) { 
        double t = hueFactor.get(); 
        t -= .5; 
        if (t < 0) 
         t = 0; 
        hueFactor.set(t); 
       } 

       if (event.getCode() == KeyCode.N) 
        hueOffset.set(hueOffset.get() + 10); 
       if (event.getCode() == KeyCode.B) { 
        double t = hueOffset.get(); 
        t -= 10; 
        if (t < 0) 
         t = 0; 
        hueOffset.set(t); 
       } 

      } 
     }); 

     scene.widthProperty().addListener((observableValue, oldSceneWidth, newSceneWidth) -> { 
      System.out.println("Width: " + newSceneWidth); 
      int newValue = newSceneWidth.intValue(); 
      if (newValue < IMAGE_MAX_WIDTH) { 
       sip1.set(newValue); 
      } 
     }); 

     scene.heightProperty().addListener((observableValue, oldSceneHeight, newSceneHeight) -> { 
      System.out.println("Height: " + newSceneHeight); 
      int newValue = newSceneHeight.intValue(); 
      if (newValue < IMAGE_MAX_HEIGHT) { 
       sip2.set(newValue); 
      } 
     }); 
     primaryStage.setTitle("JavaFX Demo"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

Ergebnis: enter image description here

+0

Vermutlich in 'renderImage()' Sie müssen auch den 'ImageView' aktualisieren die neuen anzuzeigen' WritableImage' Sie erstellt. –

+0

@ Enigo, ich verstehe, was Sie tun, ist der Code lauffähig, aber das Prog erzeugt nur ein weißes Bild ;-( – Sascha

+0

@Sascha seltsam, nur getestet. Lassen Sie mich den gesamten Code dann – Enigo

Verwandte Themen