Skip to content

Tag: comic

JavaFX, comic balloon

A example of how flexible can be extending your own Custom Node. In this example I’m creating a comic ballon that can be simple created by:

Ballon {
   text: "I can has fx?"
}

That can also be incremented to work like this:

[youtube:http://br.youtube.com/watch?v=LexJbO1-ti4]

Here a simpler implementation of a balloon, without the dragging behavior but that can be used for creating comics.

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.geometry.Ellipse;
import javafx.scene.geometry.Polygon;
import javafx.scene.geometry.ShapeSubtract;
import javafx.scene.paint.Color;
import javafx.scene.Font;
import javafx.scene.text.Text;
import javafx.scene.FontStyle;
import java.lang.Math;

public class Balloon extends CustomNode {  

    /* (cx,cy) center of the balloon */
    public attribute cx: Number = 100 on replace {
        distance = Math.sqrt(toX * toX + toY * toY);
    }
    public attribute cy: Number = 100 on replace {
        distance = Math.sqrt(toX * toX + toY * toY);
    }

    /* (toX, toY) point where balloon points at */
    public attribute toX: Number = cx on replace {
        distance = Math.sqrt(toX * toX + toY * toY);
    }
    public attribute toY: Number = cy on replace {
        distance = Math.sqrt(toX * toX + toY * toY);
    }

    /* what is writted in the balloon */
    public attribute text: String = "balloon";

    /* font for the text */
    public attribute font: Font = Font {
        size: 24
        style: FontStyle.PLAIN
    }

    /* Distance between (cx,cy) and (toX, toY) */
    private attribute distance: Number;

    /* Text inside the balloon */
    private attribute label = Text {
        font: bind font
        content: bind text
    }

    /* place the label correctly based on text */
    init {
        label.x = -label .getWidth() / 2;
        label.y = label.font.size / 2;
    }

    /* ballon body */
    private attribute body = ShapeSubtract{
        fill: Color.WHITE
        stroke: Color.BLACK
        blocksMouse: true
        a:  bind [
            Ellipse {
                radiusX: bind label.getWidth() / 2 + 20
                radiusY: bind font.size * 2
            },
            Polygon {
                points : [
                    10 * ( - toY / distance),
                    10 * (toX / distance),
                    10 * (toY / distance),
                    10 * ( - toX / distance),
                    toX,
                    toY
                ]
            }
        ]
    }

    public function create(): Node {
        return Group {
            cursor: Cursor.HAND
            content: [ body, label]
            translateX: bind cx
            translateY: bind cy
        }
    }
}