I grabbed a bunch of code from different places and did not clean it up.
This is a sloppy/quick implementation, but it's a start. It's clickable and editable.
BubbleShape.java
import java.io.*;
import javafx.event.*;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.layout.*;
/**
 *
 * @author Sedrick
 */
public class BubbleShape extends StackPane {
    TextArea textArea = new TextArea();
    ImageView bubbleShape;
    BubbleShape(String text)
    {
        textArea.setText(text);
        textArea.setPrefSize(200, 200);
        textArea.setMaxSize(200, 200);
        textArea.setEditable(false);
        textArea.setWrapText(true);
        File file = new File("bubble_shape.png");
        if (file.exists())
        {
            bubbleShape = new ImageView(new Image(file.toURI().toString()));
            bubbleShape.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event)
                {
                    Alert alert = new Alert(AlertType.ERROR);
                    alert.setTitle("Exception Dialog");
                    alert.setHeaderText("Look, an Exception Dialog");
                    alert.setContentText("Could not find file blabla.txt!");
                    Label label = new Label("The exception stacktrace was:");
                    TextArea tempTextArea = new TextArea();
                    tempTextArea.setEditable(true);
                    tempTextArea.setWrapText(true);
                    tempTextArea.setMaxWidth(Double.MAX_VALUE);
                    tempTextArea.setMaxHeight(Double.MAX_VALUE);
                    GridPane.setVgrow(tempTextArea, Priority.ALWAYS);
                    GridPane.setHgrow(tempTextArea, Priority.ALWAYS);
                    GridPane expContent = new GridPane();
                    expContent.setMaxWidth(Double.MAX_VALUE);
                    expContent.add(label, 0, 0);
                    expContent.add(tempTextArea, 0, 1);
                    alert.getDialogPane().setExpandableContent(expContent);
                    alert.showAndWait();
                    textArea.setText(tempTextArea.getText());
                }
            });
            textArea.setOnMouseClicked(new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent event)
                {
                    Alert alert = new Alert(AlertType.ERROR);
                    alert.setTitle("Exception Dialog");
                    alert.setHeaderText("Look, an Exception Dialog");
                    alert.setContentText("Could not find file blabla.txt!");
                    Label label = new Label("The exception stacktrace was:");
                    TextArea tempTextArea = new TextArea();
                    tempTextArea.setEditable(true);
                    tempTextArea.setWrapText(true);
                    tempTextArea.setMaxWidth(Double.MAX_VALUE);
                    tempTextArea.setMaxHeight(Double.MAX_VALUE);
                    GridPane.setVgrow(tempTextArea, Priority.ALWAYS);
                    GridPane.setHgrow(tempTextArea, Priority.ALWAYS);
                    GridPane expContent = new GridPane();
                    expContent.setMaxWidth(Double.MAX_VALUE);
                    expContent.add(label, 0, 0);
                    expContent.add(tempTextArea, 0, 1);
                    // Set expandable Exception into the dialog pane.
                    alert.getDialogPane().setExpandableContent(expContent);
                    alert.showAndWait();
                    textArea.setText(tempTextArea.getText());
                }
            });
        }
        else
        {
            System.out.println("File does not exits1");
        }
        this.getChildren().addAll(textArea, bubbleShape);
    }
}
Main.java
import javafx.application.*;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.*;
/**
 *
 * @author Sedrick
 */
public class JavaFXApplication14 extends Application {
    @Override
    public void start(Stage stage) throws Exception
    {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        launch(args);
    }
}
Controller
import java.net.*;
import java.util.*;
import javafx.fxml.*;
import javafx.scene.layout.*;
/**
 *
 * @author Sedrick
 */
public class FXMLDocumentController implements Initializable {
    @FXML
    AnchorPane apMain;
    @Override
    public void initialize(URL url, ResourceBundle rb)
    {
         BubbleShape bs = new BubbleShape("Hello world!");
         bs.setLayoutX(50.0);
         bs.setLayoutY(50.0);
         BubbleShape bs2 = new BubbleShape("Bye world!");
         bs2.setLayoutX(400);
         bs2.setLayoutY(400);
         apMain.getChildren().addAll(bs, bs2);
    }
}
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" fx:id="apMain" prefHeight="749.0" prefWidth="973.0" stylesheets="@makeTextAreaTransparent.css" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication14.FXMLDocumentController">
</AnchorPane>
CSS: makeTextAreaTransparent.css
.text-area {
    -fx-background-color: rgba(53,89,119,0.4);
}
.text-area .scroll-pane {
    -fx-background-color: transparent;
}
.text-area .scroll-pane .viewport{
    -fx-background-color: transparent;
}
.text-area .scroll-pane .content{
    -fx-background-color: transparent;
}
