A DESCRIPTION OF THE REQUEST :
The creation of TextField instances is quite slow.
From looking into the profiler we see that most of the time is burned in the creation of TextFieldSkin, during CSS processing.
JUSTIFICATION :
We have scenarios in which there are some hundred (sometimes more than 1.000) TextField instances within one dialog. The duration of building up these screens is too long (> 1 second on end user machines).
The dialogs were transferred from Swing, where there was no performance issue with JTextField.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TextField should not be a "heavy object".
There should not be significant performance issues when working with TextFields.
ACTUAL -
TextField is a "heavy object".
As result we have to implement "strange bypass solutions", e.g. we render simple Text-instances first and the switch over to TextField if the user accesses the component (focus). - This of course has disadvantages in the area of usability...
---------- BEGIN SOURCE ----------
/* Creation of a lot of TextField instances with some stopwach, */
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Test_91_Performance
extends Application
{
public static void main(String[] args)
{
launch(args);
}
static final int nofCols = 100;
static final int nofRows = 30;
VBox m_vb = new VBox();
Label m_label;
long m_startTime;
@Override
public void start(Stage primaryStage)
{
StackPane sp = new StackPane();
m_vb = new VBox();
sp.getChildren().add(m_vb);
{
Button b = new Button("Create Controls - Start stopwatch!");
m_vb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
buildControlsOneByOne();
}
});
}
{
HBox hb = new HBox(10);
m_vb.getChildren().add(hb);
Button b = new Button("I see the controls - Stop stopwatch!");
hb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
stopMeasuring();
}
});
m_label = new Label();
hb.getChildren().add(m_label);
}
{
Button b = new Button("Clear controls");
m_vb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
clearControls();
}
});
}
Scene scene = new Scene(sp);
primaryStage.setWidth(1800);
primaryStage.setHeight(1000);
primaryStage.setScene(scene);
primaryStage.show();
}
private void clearControls()
{
long stampBegin = System.currentTimeMillis();
int max = m_vb.getChildren().size()-1;
for (int i=max; i>=3; i--)
{
m_vb.getChildren().remove(i);
}
long stampEnd = System.currentTimeMillis();
System.out.println("Duration: " + (stampEnd - stampBegin));
}
private void stopMeasuring()
{
long duration = System.currentTimeMillis() - m_startTime;
System.out.println("Duration until controls are visible: " + duration);
m_label.setText("Stopped duration: " + duration + " ms");
}
private void buildControlsOneByOne()
{
long stampBegin = System.currentTimeMillis();
m_startTime = stampBegin;
for (int i=0; i<nofRows; i++)
{
HBox hb = new HBox();
m_vb.getChildren().add(hb);
List<Node> rowNodes = new ArrayList<>();
for (int j=0; j<nofCols; j++)
{
TextField f = new TextField();
hb.getChildren().add(f);
}
}
long stampEnd = System.currentTimeMillis();
System.out.println("Internal Duration for creation: " + (stampEnd - stampBegin));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
As mentioned above: we (have to) bypass by using "not heavy" components (Text) until the user selects, and then switch to the "heavy" component.
But this bypass has usability-disadvantages (e.g. caret position not where user expects it to be). And it's quite complicated, so it's difficult to apply for normal scenarios.
The creation of TextField instances is quite slow.
From looking into the profiler we see that most of the time is burned in the creation of TextFieldSkin, during CSS processing.
JUSTIFICATION :
We have scenarios in which there are some hundred (sometimes more than 1.000) TextField instances within one dialog. The duration of building up these screens is too long (> 1 second on end user machines).
The dialogs were transferred from Swing, where there was no performance issue with JTextField.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
TextField should not be a "heavy object".
There should not be significant performance issues when working with TextFields.
ACTUAL -
TextField is a "heavy object".
As result we have to implement "strange bypass solutions", e.g. we render simple Text-instances first and the switch over to TextField if the user accesses the component (focus). - This of course has disadvantages in the area of usability...
---------- BEGIN SOURCE ----------
/* Creation of a lot of TextField instances with some stopwach, */
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Test_91_Performance
extends Application
{
public static void main(String[] args)
{
launch(args);
}
static final int nofCols = 100;
static final int nofRows = 30;
VBox m_vb = new VBox();
Label m_label;
long m_startTime;
@Override
public void start(Stage primaryStage)
{
StackPane sp = new StackPane();
m_vb = new VBox();
sp.getChildren().add(m_vb);
{
Button b = new Button("Create Controls - Start stopwatch!");
m_vb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
buildControlsOneByOne();
}
});
}
{
HBox hb = new HBox(10);
m_vb.getChildren().add(hb);
Button b = new Button("I see the controls - Stop stopwatch!");
hb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
stopMeasuring();
}
});
m_label = new Label();
hb.getChildren().add(m_label);
}
{
Button b = new Button("Clear controls");
m_vb.getChildren().add(b);
b.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
clearControls();
}
});
}
Scene scene = new Scene(sp);
primaryStage.setWidth(1800);
primaryStage.setHeight(1000);
primaryStage.setScene(scene);
primaryStage.show();
}
private void clearControls()
{
long stampBegin = System.currentTimeMillis();
int max = m_vb.getChildren().size()-1;
for (int i=max; i>=3; i--)
{
m_vb.getChildren().remove(i);
}
long stampEnd = System.currentTimeMillis();
System.out.println("Duration: " + (stampEnd - stampBegin));
}
private void stopMeasuring()
{
long duration = System.currentTimeMillis() - m_startTime;
System.out.println("Duration until controls are visible: " + duration);
m_label.setText("Stopped duration: " + duration + " ms");
}
private void buildControlsOneByOne()
{
long stampBegin = System.currentTimeMillis();
m_startTime = stampBegin;
for (int i=0; i<nofRows; i++)
{
HBox hb = new HBox();
m_vb.getChildren().add(hb);
List<Node> rowNodes = new ArrayList<>();
for (int j=0; j<nofCols; j++)
{
TextField f = new TextField();
hb.getChildren().add(f);
}
}
long stampEnd = System.currentTimeMillis();
System.out.println("Internal Duration for creation: " + (stampEnd - stampBegin));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
As mentioned above: we (have to) bypass by using "not heavy" components (Text) until the user selects, and then switch to the "heavy" component.
But this bypass has usability-disadvantages (e.g. caret position not where user expects it to be). And it's quite complicated, so it's difficult to apply for normal scenarios.