7 de jan. de 2017

Desenvolvimento rápido de aplicações de efeitos visuais com JavaFX

Quem acompanha o blog notou que ultimamente temos postado somente aplicações mais visuais sempre se baseando nos vídeos do mestre Daniel Shiffman. Pois bem, ele usa Processing, uma outra linguagem de programação e esse é um blog sobre JavaFX e o nosso objetivo é também sempre se manter em contato com Java - em outras palavras, quero "levar a palavra" do Shiffman para o mundo e ainda exercitar Java. A palavra de Shiffman é a seguinte:

"Processing, for me, has always been just the most wonderful thing ever. It’s given me a mission and a passion, to bring computation to everyone: artists, designers, musicians, biologists, doctors, dancers, animators, bankers, photographers, librarians, fashion designers, architects, psychologists, journalists, and writers, just to name a few. Writing code can be scary, something many mistakenly think is reserved for computer scientists and engineers. Processing has helped eliminate that fear, making programming accessible to a wider audience, particularly artists.”

Fonte: Wikipedia

Ou seja, ele encontrou em processing uma forma de levar programação a mais pessoas. Com JavaFX não é diferente, é possível programar e criar aplicações sem ser um mestre Java - mas, a linguagem ainda aparece as vezes como um empecilho. Eu escrevo esse blog há 4 anos e estou "mexendo" com JavaFX desde a primeira versão, uns 8 anos já e vejo isso acontecendo.
Mas por que o blog então não é sobre Processing? O motivo é que Java é super importante para o mercado e "brincando" com JavaFX você exercita Java também, mas é necessário o equilibrio para que a linguagem Java não seja um empecilho.

Resumindo, criei uma classe que estou usando em aplicações visuais que "imita" o processing - mas é claro que o Processing é um universo a parte, a ideia é tirar partes repetitivas para que se tenha o foco na aplicação visual. O nome da classe é "DrawingApp", como já visto no post sobre as flores e no post sobre o algoritmo Metaballs.
Veja abaixo o exemplo de uma aplicação simples (bolas coloridas) que usa a DrawingApp e o código da classe DrawingApp.

package org.fxapps.drawingfx;
import javafx.scene.paint.Color;
public class BouncingBalls extends DrawingApp {
Ball[] balls = new Ball[20];
public static void main(String[] args) {
launch();
}
@Override
void setup() {
title = "Bouncing Ball Example";
width = 800;
height = 600;
for (int i = 0; i < balls.length; i++) {
balls[i] = new Ball(width / 2, height / 2);
}
}
@Override
void draw() {
ctx.setFill(Color.LIGHTGRAY);
ctx.fillRect(0, 0, width, height);
for (Ball ball : balls) {
ball.update();
ball.show();
}
}
class Ball {
int x, y, r, speedX, speedY;
Color c;
public Ball(int x, int y) {
this.x = x;
this.y = y;
this.c = Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255));
r = random.nextInt(100);
speedX = 40 - random.nextInt(40) - 20;
speedY = random.nextInt(40) - 20;
}
void update() {
this.x+= speedX;
this.y+= speedY;
if(x < 0 || x > width) {
speedX *= -1;
}
if(y < 0 || y > height) {
speedY *= -1;
}
}
void show() {
ctx.setFill(c);
ctx.fillOval(x, y, r, r);
}
}
}
package org.fxapps.drawingfx;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* Class to quick start drawing with JavaFX. Just extend this class and create your application!
*
* @author wsiqueir
*
*/
public abstract class DrawingApp extends Application {
public int frames = 10;
public String title = "My App";
public static int width = 600;
public static int height = 400;
public static Random random = new Random();
Canvas canvas = new Canvas();
GraphicsContext ctx = canvas.getGraphicsContext2D();
@Override
public void start(Stage stage) throws Exception {
setup();
canvas.setHeight(height);
canvas.setWidth(width);
canvas.setOnMouseClicked(this::mouseCliked);
canvas.setOnMouseDragged(this::mouseDragged);
canvas.setOnMouseMoved(this::mouseMoved);
canvas.setOnMouseEntered(this::mouseEntered);
canvas.setOnMouseExited(this::mouseExited);
canvas.setOnKeyPressed(this::keyPressed);
canvas.setOnKeyTyped(this::keyTyped);
canvas.setOnKeyReleased(this::keyReleased);
StackPane raiz = new StackPane(canvas);
stage.setTitle(title);
stage.setScene(new Scene(raiz, width, height));
stage.show();
canvas.requestFocus();
KeyFrame frame = new KeyFrame(Duration.millis(1000 / frames), e -> draw());
Timeline timeline = new Timeline(frame);
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.play();
}
// classical setup and draw methods from Processing
void setup() {
}
void draw() {
}
// event listeners - if user override the method with event, the method
// without event won't be called
public void mouseCliked(MouseEvent e) {
mouseCliked();
}
public void mouseDragged(MouseEvent e) {
mouseDragged();
}
public void mouseMoved(MouseEvent e) {
mouseMoved();
}
public void mouseEntered(MouseEvent e) {
mouseEntered();
}
public void mouseExited(MouseEvent e) {
mouseExited();
}
public void keyPressed(KeyEvent e) {
keyPressed();
}
public void keyTyped(KeyEvent e) {
keyTyped();
}
public void keyReleased(KeyEvent e) {
keyReleased();
}
public void mouseCliked() {
}
public void mouseDragged() {
}
public void mouseMoved() {
}
public void mouseEntered() {
}
public void mouseExited() {
}
public void keyPressed() {
}
public void keyTyped() {
}
public void keyReleased() {
}
/*
* Utility methods
*/
public double distance(double x, double y, double x2, double y2) {
return sqrt(pow(x2 - x, 2) + pow(y2 - y, 2));
}
}
view raw DrawingApp.java hosted with ❤ by GitHub

Nenhum comentário:

Postar um comentário