Skip to content

Instantly share code, notes, and snippets.

@james-d
Created March 30, 2014 13:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save james-d/9872945 to your computer and use it in GitHub Desktop.
Save james-d/9872945 to your computer and use it in GitHub Desktop.
Experiment with creating a reusable ExpandableTextArea that grows/shrinks according to the text inside it. This is a bit of a hack: uses a lookup and an AnimationTimer to execute the lookup when the css styles have been applied.
package expandabletextarea;
import java.util.concurrent.Callable;
import javafx.animation.AnimationTimer;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.control.TextArea;
public class ExpandableTextArea extends TextArea {
public ExpandableTextArea(String text) {
super(text);
setMinHeight(24);
new AnimationTimer() {
@Override
public void handle(long now) {
Node text = lookup(".text");
if (text != null) {
prefHeightProperty().bind(
Bindings.createDoubleBinding(
new Callable<Double>() {
@Override
public Double call() throws Exception {
return text.getBoundsInLocal().getHeight();
}
}, text.boundsInLocalProperty()).add(20));
this.stop();
}
}
}.start();
}
public ExpandableTextArea() {
this("");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Tab?>
<?import expandabletextarea.ExpandableTextArea?>
<BorderPane xmlns:fx="http://javafx.com/fxml">
<center>
<TabPane>
<tabs>
<Tab text="Tab 1">
<content>
<VBox>
<ExpandableTextArea text="Text area 1" />
</VBox>
</content>
</Tab>
<Tab text="Tab 2">
<content>
<VBox>
<ExpandableTextArea text="Text area 2" />
</VBox>
</content>
</Tab>
<Tab text="Tab 3">
<content>
<VBox>
<ExpandableTextArea text="Text area 3" />
</VBox>
</content>
</Tab>
</tabs>
</TabPane>
</center>
</BorderPane>
package expandabletextarea;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("ExpandableTextAreaTest.fxml"));
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
@ruslooob
Copy link

this code has memory leak because it uses AnimationTimer class with heavy action. During time this control will be consume huge amount of memory. Do not use it!

@james-d
Copy link
Author

james-d commented Oct 6, 2023

this code has memory leak because it uses AnimationTimer class with heavy action. During time this control will be consume huge amount of memory. Do not use it!

The AnimationTimer does essentially nothing until the lookup succeeds, and when the lookup succeeds, it stops. It won't consume any appreciable memory.

@ruslooob
Copy link

ruslooob commented Nov 3, 2023

@james-d Our company used this code in production. And after profiling the app, we found out that this class consumed near 80% of all app memory when opening the application for a long time (for example for 10 hour running app).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment