Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Grafica e multimedialità con JavaFX

Inserire grafica, testo, suoni ed effetti nelle nostre applet JavaFX
Inserire grafica, testo, suoni ed effetti nelle nostre applet JavaFX
Link copiato negli appunti

JavaFX è l'insieme di strumenti per la creazione di Rich Internet Application messa in campo dalla piattaforma Java. Abbiamo già fatto la conoscenza di questa tecnologia in un articolo precedente, quindi possiamo tralasciare i convenevoli e concentrarci sulle funzionalità più specifiche.

In particolare approfondiremoo, con esempi pratici, alcune funzioni multimediali. Utilizzeremo anche del sistema di Applet Extension che permette il drag'n'drop dell'applicazione dal browser al desktop: la vera innovazione di questo linguaggio.

Vedremo come:

  • realizzare effetti grafici
  • utilizzare immagini e componenti multimediali
  • utilizzare le animazioni
  • realizzare una semplice applicazione da trascinare sul desktop

Ci soffermeremo sui diversi aspetti in un percorso in cui costruiremo, esempio dopo esempio, una piccola soluzione.

Il contenitore

Per prima cosa dobbiamo costruire il contenitore che ospiterà i diversi oggetti che stiamo per osservare. Definiamo così il nostro Stage di base:

var stage:Stage = Stage {
     title : "MyApp"
     scene: Scene { width: 400 height: 200
                    content: [
                       // inseriremo qui i diversi oggetti
                    ]
                  }
}

Vedremo che ci sarà utile definire un'istanza di Stage: ci permetterà di sfruttare alcune proprietà del contenitore.

Effetti grafici

Iniziamo ad esaminare alcuni oggetti del namespace javafx.scene, che contiene forme di base, colori ed effetti.

L'oggetto javafx.scene.paint.Color contiene una serie di colori di base, mentre gli oggetti grafici (superclassi di javafx.scene.shape.Shape) possono essere colorati nel contenuto e nel bordo, possono avere anche degli effetti grafici, come ad esempio un punto di luce.

Iniziamo subito con del codice, che poi commenteremo:

// Definiamo una variabile per il colore del bordo
var strokeColor:Color = Color.GOLD;
// Creiamo un rettangolo contenente un punto di luce
var drawRectangle:Rectangle = Rectangle { 
    x: 0
    y: 0
    width: bind stage.width
    height: bind stage.height
    fill: Color.ALICEBLUE
    stroke: strokeColor
    strokeWidth:15
    effect: Lighting {
                 light: PointLight {
                      x: bind stage.width/2
                      y: bind stage.height/2
                      z: 50
                 }
                 surfaceScale: 5
            }
}

Nella sezione content della scena richiamiamo il nostro rettangolo:

content: [
       // inseriremo qui i diversi oggetti
       drawRectangle
    ]

L'effetto ottenuto è il seguente:

In questo caso abbiamo un rettangolo che ha come colore di riempimento ALICEBLUE e un bordo dorato (GOLD). Al centro del rettangolo abbiamo posizionato un punto di luce nel quale è specificata la posizione attraverso le coordinate spaziali x, y e z.

È importante sottolineare che abbiamo potuto calcolare e applicare la posizione della luce grazie alla parola chiave 'bind' e grazie al fatto che abbiamo dato un nome (stage) alla nostra istanza di Stage.

Riconoscere un'applet

javafx.lang.FX è un singleton, svolge una funzione simile a quella di java.lang.System in java, può leggere il contenuto di variabili di sistema (come javafx.user.home, javafx.os.name javafx.screen.width, etc..), leggere argomenti dalla VM (virtual machine) o semplicemente chiudere l'applicazione (FX.exit() ).

Inoltre, la funzione FX.getArgument("isApplet") ci dà informazioni circa il contesto in cui stiamo utilizzando l'applicazione. In pratica, leggiamo se è presente isApplet tra gli argomenti di lancio.

Aggiungiamo all'esempio precedente un paio di dichiarazioni:

// Dichiariamo due valori booleani
var isApplet = "true".equals(FX.getArgument("isApplet") as String);
var inbrowser = not isApplet;
// Poi dichiariamo un colore,
// che dipende dal valore assunto dalla variabile
var strokeColor:Color = bind {
  if(inbrowser) { Color.BEIGE }
  else { Color.GOLD }
}

In questo modo il bordo del rettangolo cambierà colore a seconda che lanciamo l'applicazione come applet o meno.

Immagini

Per includere le immagini nella nostra applicazione possiamo semplicemente inserirle all'interno del package dell'applicazione. Per mostrarle poi sfruttiamo gli oggetti:

javafx.scene.image.Image
javafx.scene.image.ImageView

Image si occupa della gestione del sorgente dell'immagine che vogliamo utilizzare e ImageView di renderizzarla nell'applicazione, come ogni altro nodo (javafx.scene.Node):

var logo:Image = Image {
    url: "{__DIR__}logo.png"
    width: 50
    height: 50
} 
var imageView:ImageView = ImageView{
    x: 10
    y: 10
    image: logo
}

Componenti multimediali

Proviamo ora a inserire una canzone come musica di sottofondo. Definiamo un oggetto javafx.scene.media.Media che si occupa della gestione del sorgente:

var baseURL:String = "music";
var filename:String = "sound.wav";
var song = Media {
            source: "{__DIR__}{baseURL}/{filename}"
            onError: function(e:MediaError) {
              println("errore  {e}");
            }
}

Includiamo l'oggetto Media in un'istanza di javafx.scene.media.MediaPlayer per la gestione del componente:

var mediaPlayer:MediaPlayer = MediaPlayer{
    media: song
}

Infine, al verificarsi di un qualsiasi evento nel quale vogliamo far partire il contenuto multimediale, eseguiamo:

mediaPlayer.play();

In conclusione, la gestione del file multimediale è delegata all'oggetto javafx.scene.media.Media, in cui è possibile specificare caratteristiche come la durata, o l'altezza e la larghezza se si tratta di un file video.

La fruizione del contenuto multimediale, invece, è delegata all'oggetto javafx.scene.media.MediaPlayer, che si occupa di integrarlo nell'applicazione.

Il Deployment delle applet

È importante spendere qualche parola sul deployment delle applet realizzate con JavaFX. Una volta compilato il sorgente e lanciato il packager (vedi articolo precedente), viene creata una cartella dist, nella quale troviamo il file .jar dell'applicazione, due file .jnlp e un file HTML.

Nel file HTML troviamo il codice necessario all'embed dell'applet sulla nostra pagina:

<script src="http://dl.javafx.com/1.2/dtfx.js"></script>
<script>
    javafx(
        {
              archive: "percorsoApplicazione/nomeApplicazione.jar",
              width: 400,
              height: 200,
              code: "nomeApplicazione",
              name: "nomeApplicazione"
        }
    );
</script>

Prima di inserire questo codice nella pagina che ospiterà l'applet, perché tutto funzioni, dobbiamo caricare sul server i due file:

  • nomeApplicazione.jar
  • nomeApplicazione_browser.jnlp

e stare molto attenti agli URL.

Il file nomeApplicazione_browser.jnlp, infatti è un descrittore dell'applicazione ed indica al plugin java del nostro browser alcune informazioni, come l'indirizzo di base dell'applicazione. Se non indichiamo al plugin l'esatta posizione dei nostri file questo potrebbe non caricare l'applet!

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://percorsoApplicazione/" href="rect01_browser.jnlp">
    <information>
        <title>nomeApplicazione</title>
        <vendor>andimar</vendor>
        <homepage href="http://percorsoApplicazione/"/>
        <description>nomeApplicazione</description>
        <offline-allowed/>
        <shortcut>
            <desktop/>
        </shortcut>
    </information>
    <resources>
        <j2se version="1.5+"/>
        <extension name="JavaFX Runtime" href="http://dl.javafx.com/1.2/javafx-rt.jnlp"/>
        <jar href="nomeApplicazione.jar" main="true"/>
    </resources>
    <applet-desc name="nomeApplicazione" main-class="com.sun.javafx.runtime.adapter.Applet"  >
        <param name="MainJavaFXScript" value="nomeApplicazione">
    </applet-desc>
    <update check="background">
</jnlp>

Nella seconda parte dell'articolo vedremo come creare animazioni e transizioni e come trascinare un'applet e trasformarla in una applicazione desktop.

Le Animazioni

JavaFX possiede nativamente una ricca dotazione di animazioni. Grazie alla programmazione dichiarativa possiamo definire e applicare animazioni indipendentemente dagli oggetti che ne sono coinvolti. Questo ci permette di scegliere una delle animazioni disponibili e semplicemente applicarla ad uno degli oggetti che abbiamo già presenti sulla scena, poi se l'effetto non ci piace, cancellare tutto e applicare un altro movimento.

Tutto ciò di cui abbiamo bisogno è il riferimento all'oggetto grafico da animare e di impostare alcuni parametri. Vediamo subito un esempio. Dichiariamo un un oggetto testo in questo modo:

var title:Text = Text {
     effect: Lighting {
            light: SpotLight {
                x: 0
                y: 100
                z: 50
                pointsAtX: 400
                pointsAtY: 0
                pointsAtZ: 0
                specularExponent: 2
                color: Color. FIREBRICK
            }
            surfaceScale: 5
        }
    font : Font.font(null, FontWeight.BOLD, 26)
    fill: Color.WHITE
    stroke: Color.WHITE
    x: 60
    y: 100
    content: bind "Simple applicationn on {testo}"
}

Definiamo un effetto di rotazione e lo colleghiamo al nodo grafico che ci interessa animare:

var rotateTransition = RotateTransition {
    duration: 18s
    node: title
    byAngle: 90
    fromAngle: -270
    toAngle: 0
    repeatCount:1
    autoReverse: true
    framerate: 60
}

così facendo, abbiamo definito una trasizione circolare di un gruppo di componenti grafici, della durata di 18 secondi, dall'angolo 90° a ruotando per i 270° rimanenti, con un framerate di 60 fotogrammi/sec. Questo ha un grande potenziale perché ci si può concentrare prima sul disegno grafico dell'applicazione e poi sulla gestione delle animazioni.

Infine, al verificarsi di un evento la facciamo partire, come per le risorse multimediali, attraverso il metodo play():

rotateTransition.play();

Un altro esempio:

var translateTransition = TranslateTransition {
    duration: 12s
    node: imageView
    byX: 300
    repeatCount: 2
    autoReverse: true
    framerate: 60
}
translateTransition.play();

Questa è una traslazione dell'oggetto imageView di 300 pixel, della durata di 12 secondi, con frequenza di aggiornamento a 60 fotogrammi/sec.

Applet Extension

Una delle caratteristiche interessanti di JavaFX è la possibilità di trascinare, con un semplice drag'n'drop, l'applet che visualizziamo sul sito, all'interno del desktop. Questa operazione cambia il contesto operativo dell'applicazione e, come abbiamo visto nelle pagine precendenti, siamo in grado di gestire lo switch tra le due modalità.

Per implementare l'Applet Extension dobbiamo utilizzare un'estensione della classe Stage: javafx.stage.AppletStageExtension.

Ecco un esempio:

var stage = Stage {
    title: "Simple Application"
    width: 400
    height: 200
    scene: Scene {
      content: [
         drawRectangle,
         title
      ]
    }
    extensions: [
      AppletStageExtension {
          // Definisce la combinazione di eventi
          // attraverso cui inizia il drag'n'drop
          // dell'applet al di fuori del browser
          shouldDragStart: function(e): Boolean {
            return e.primaryButtonDown and title.hover;
          }
          //Evento di chiusura dell'operazione di trascinamento
          onDragFinished: function(): Void  {
            inbrowser=false;
          }
          onAppletRestored: function(): Void  {
            inbrowser=true;
          }
          onDragStarted: function(): Void {
            // appena esternalizzata
            // parte la musica di sottofondo
            mediaPlayer.play();
          }
          useDefaultClose: true
      }
    ]
}

Attraverso l'evento shouldDragStart specifichiamo la condizione al verificarsi della quale l'applet perde l'integrazione col browser e può essere spostata a piacimento sul desktop.

Gli eventi onDragStarted e onAppletRestore sono invocati rispettivamente quando l'applet si stacca dal browser e quando, da applicazione, ci ritorna.

Se chiudiamo il browser con l'applicazione esternalizzata, le routine di JavaWebStart ci chiederanno se vogliamo il link dell'applicazione sul desktop, che dà la possibilità di riaprire l'applicazione in un altro momento, ndipendentemente dal browser.

Se non chiudiamo il browser, premendo la X di chiusura l'applicazione ritorna ad essere una applet; se il browser è chiuso, chiuderemo anche l'applicazione.

Nota: perché tutto funzioni correttamente occorre ricordare di aggiungere al comando javafxpackager l'opzione -draggable e di aggiungere la dichiarazione draggable:true nella funzione javafx() che richiama l'applet.

Ecco l'esempio completo:

Tutto il codice degli esempi è contenuto nel file in allegato.

Ti consigliamo anche