I'm trying to implement drag&drop for ListView each cell of which is a GridPane. So, I'm just making snapshot of a corresponding GridPane and set is drag view.
WritableImage im = rootPane.snapshot(null, null);
dragboard.setDragView(im);
The problem is that size of drag view image is somehow scaled down and I have no idea why is that.
I've tried to scale snapshot image but has no luck.
WritableImage writableImage = new WritableImage((int)(5 * getWidth()), (int)(5 * getHeight()));
SnapshotParameters sp = new SnapshotParameters();
sp.setTransform(Transform.scale(5, 5));
WritableImage im = rootPane.snapshot(sp, writableImage);
Could someone please explain how to show real image size when dragging.
EDIT:
Minimal reproducible example. Also I've noticed that the size of the drag view depends on... scene size. The larger scene size the lower drag view will be
public class Launcher extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
BorderPane pane = new BorderPane();
ListView<Foo> fooList = new ListView<>();
pane.setCenter(fooList);
fooList.setCellFactory(list -> new FooCell());
fooList.getItems().setAll(List.of(new Foo("1"), new Foo("2"), new Foo("3"), new Foo("4")));
Scene scene = new Scene(pane, 1400, 900);
primaryStage.setTitle("Demo");
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(t -> Platform.exit());
primaryStage.show();
}
static class Foo {
public String a;
public Foo(String a) {
this.a = a;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Foo foo = (Foo) o;
return a.equals(foo.a);
}
#Override
public int hashCode() {
return a.hashCode();
}
}
static class FooCell extends ListCell<Foo> {
private AnchorPane rootPane;
private GridPane gridPane;
private Region dragHandle;
private TextField textField;
private HBox hbox;
public FooCell() {
ListCell<Foo> thisCell = this;
rootPane = new AnchorPane();
gridPane = new GridPane();
gridPane.setPrefHeight(40);
AnchorPane.setTopAnchor(gridPane, 0d);
AnchorPane.setRightAnchor(gridPane, 0d);
AnchorPane.setBottomAnchor(gridPane, 0d);
AnchorPane.setLeftAnchor(gridPane, 0d);
rootPane.getChildren().setAll(gridPane);
dragHandle = new Region();
dragHandle.setMinWidth(30);
setOnDragDetected(event -> {
if (getItem() == null) return;
ObservableList<Foo> items = getListView().getItems();
Dragboard dragboard = startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(getItem().a);
dragboard.setDragView(gridPane.snapshot(null, null));
dragboard.setContent(content);
event.consume();
});
setOnDragOver(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
});
setOnDragEntered(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
setOpacity(0.3);
}
});
setOnDragExited(event -> {
if (event.getGestureSource() != thisCell && event.getDragboard().hasString()) {
setOpacity(1);
}
});
setOnDragDropped(event -> {
if (getItem() == null) return;
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
ObservableList<Foo> items = getListView().getItems();
int draggedIdx = items.indexOf(new Foo(db.getString()));
int thisIdx = items.indexOf(getItem());
items.set(draggedIdx, getItem());
items.set(thisIdx, new Foo(db.getString()));
List<Foo> itemscopy = new ArrayList<>(getListView().getItems());
getListView().getItems().setAll(itemscopy);
success = true;
}
event.setDropCompleted(success);
event.consume();
});
setOnDragDone(DragEvent::consume);
textField = new TextField();
hbox = new HBox();
ColumnConstraints col0 = new ColumnConstraints();
col0.setHgrow(Priority.NEVER);
gridPane.add(dragHandle, 0, 0, 1, 10);
ColumnConstraints col1 = new ColumnConstraints();
col1.setHgrow(Priority.ALWAYS);
gridPane.add(textField, 1, 0, 1, 1);
gridPane.add(hbox, 1, 1, 10, 1);
gridPane.getColumnConstraints().addAll(col0, col1);
}
#Override
protected void updateItem(Foo item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
return;
}
textField.setText(item.a);
setGraphic(rootPane);
}
}
}
EDIT2 (problem identified):
It's OS (or display manager to be more precise) who's scaling dragged image down. Seems like GTK backend that JavaFX uses implements kind of limitation for dragged images. If image width is greater than 300-350px it will be scaled down. I've found out this simply trying to drag various pics in my email client. Small or medium images doesn't change, but larger ones being scaled. What I've said about it depends on scene size was right, but there's no magic here. When you change scene size, you change target node size as well. When its width become close to 300px.. yeah, it was obvious, but I paid no attention.
Generally my problem is that I want to drag images that have large width, but low height. That's why scaling looks so ugly/ It makes text unreadable due to extra low font size. Funny that Electron doesn't have such problem. Either Chromium doesn't use GTK API for dragging or DOM doesn't have such issues by definition.
Related
#FXML
void minimize(MouseEvent event) {
Stage stage=(Stage) iconMinimize.getScene().getWindow();
stage.setIconified(true);
}
I have an icon that minimizes my program by mouse click. For example, when I minimize Windows for a program, you can see how the program works with an effect. The program slowly moves back to the taskbar. I would like to have such an effect too. If I do that with the code from the top, the program is right in the system tray. How do I get such an effect?
Animate the window size when you want to iconify the app and listen to the iconified property to do the reverse animation when the Stage is restored:
#Override
public void start(Stage primaryStage) {
StageHideAnimator.create(primaryStage);
Button minimize = new Button("minimize");
minimize.setOnAction(evt -> {
StageHideAnimator animator = StageHideAnimator.getStageHideAnimator((Node) evt.getSource());
animator.iconify();
});
Button close = new Button("close");
close.setOnAction(evt -> primaryStage.close());
VBox content = new VBox(minimize, close, new Rectangle(200, 200, Color.BLUE));
content.setPadding(new Insets(10));
content.setStyle("-fx-background-color: green;");
primaryStage.initStyle(StageStyle.TRANSPARENT);
Scene scene = new Scene(content);
primaryStage.setScene(scene);
primaryStage.setOnShown(evt -> {
WindowUtils.placeAtPrimaryScreenBottom(primaryStage);
});
primaryStage.show();
}
public final class WindowUtils {
private WindowUtils() { }
public static void placeAtPrimaryScreenBottom(Stage stage) {
stage.setY(Screen.getPrimary().getVisualBounds().getMaxY() - stage.getHeight());
}
}
public class StageHideAnimator {
// key used for storing animators in the properties map of a Stage
private static final Object PROPERTY_KEY = new Object();
private double sceneHeight;
private double decorationHeight;
private final Stage stage;
private Timeline animation;
// fraction of height relative to full height
private final DoubleProperty height = new SimpleDoubleProperty();
// getter for the animator
public static StageHideAnimator getStageHideAnimator(Stage stage) {
return (StageHideAnimator) stage.getProperties().get(PROPERTY_KEY);
}
// get animator of window containing the node
public static StageHideAnimator getStageHideAnimator(Node node) {
return getStageHideAnimator((Stage) node.getScene().getWindow());
}
private StageHideAnimator(Stage stage) {
this.stage = stage;
stage.iconifiedProperty().addListener((o, oldValue, newValue) -> {
// do reverse hide animation when stage is shown
if (!newValue) {
animation.setRate(-1);
if (animation.getStatus() == Animation.Status.STOPPED) {
animation.playFrom("end");
} else {
animation.play();
}
}
});
height.addListener((o, oldValue, newValue) -> {
// resize stage and put it at the bottom of the primary screen
stage.setHeight(sceneHeight * newValue.doubleValue() + decorationHeight);
WindowUtils.placeAtPrimaryScreenBottom(stage);
});
}
public static StageHideAnimator create(Stage stage) {
if (stage.getProperties().containsKey(PROPERTY_KEY)) {
// don't allow 2 animators
throw new IllegalArgumentException("animator already exists");
}
StageHideAnimator animator = new StageHideAnimator(stage);
stage.getProperties().put(PROPERTY_KEY, animator);
return animator;
}
private void initHeight() {
sceneHeight = stage.getScene().getHeight();
decorationHeight = stage.getHeight() - sceneHeight;
}
public void iconify() {
if (stage.isIconified()) {
return;
}
if (animation == null) {
initHeight(); // save initial height of stage
animation = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(height, 1d, Interpolator.EASE_BOTH)),
new KeyFrame(Duration.seconds(1), new KeyValue(height, 0d, Interpolator.EASE_BOTH)));
animation.setOnFinished(evt -> {
if (animation.getRate() == 1) {
// iconify at end of hiding animation
animation.setRate(-1);
stage.setIconified(true);
}
});
animation.play();
} else {
animation.setRate(1);
if (animation.getStatus() == Animation.Status.STOPPED) {
initHeight(); // save initial height of stage
animation.playFromStart();
} else {
animation.play();
}
}
}
}
I would like to draw autocomplete-like drop-down box near caret in JavaFX controls like TextField and TextArea.
Is it possible to know double numeric coordinates of the caret in node coordinate system?
You can use the inputMethodRequests property to retrieve the position. You can specify a index relative to the start of the selection to get the screen coordinates for the char.
private static ContextMenu createMenu(String... text) {
ContextMenu menu = new ContextMenu();
EventHandler<ActionEvent> handler = evt -> {
TextInputControl control = (TextInputControl) menu.getUserData();
String t = ((MenuItem) evt.getSource()).getText();
control.replaceSelection(t);
};
for (String s : text) {
MenuItem item = new MenuItem(s);
item.setOnAction(handler);
menu.getItems().add(item);
}
return menu;
}
#Override
public void start(Stage primaryStage) {
ContextMenu menu = createMenu("Hello World", "42", "foo", "bar");
TextArea textArea = new TextArea();
TextField textField = new TextField();
VBox root = new VBox(textArea, textField);
root.setPadding(new Insets(10));
EventHandler<KeyEvent> handler = evt -> {
if (evt.isControlDown() && evt.getCode() == KeyCode.SPACE) {
evt.consume();
TextInputControl control = (TextInputControl) evt.getSource();
Point2D pos = control.getInputMethodRequests().getTextLocation(0);
menu.setUserData(control);
menu.show(control, pos.getX(), pos.getY());
menu.requestFocus();
}
};
textArea.addEventFilter(KeyEvent.KEY_PRESSED, handler);
textField.addEventFilter(KeyEvent.KEY_PRESSED, handler);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
I've wrapped my brain around a challenge for 2 days now. I am all empty for ideas, so I hope someone out there know how to do this.
I got inspired by Angela Caicedo's city app, from the website https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx, and trying to make a similar app-gui to show available rooms and lecture halls at my University.
I am using Java FX to build the gui, and I get the whole GUI printed out, which is a java fx pane with a image on it. What I want, however, is to just see a small part of the gui (the backgroundimage I am using is w:1500px h:500, so each part will be w:500px h:500px), then be able to push a button or a arrow (or similar) to move the window to the next step. On top of the image there is 3 panes with w:500px h:500px snapped to each other. Maybe this is a bad solution, considering all the pane-types Java FX has available.
So, what I need is a constrained viewer of sorts.
I've also used FMXL to build the GUI, having one FMXL document, one Controller and a css-file to handle the design.
I'm sure I've been everywhere on the internet by now, so I really hope someone has done this before in Java FX :)
Ok, here is some code example. The first sample works nice, but I want to implement the second example instead. I am reading on the TranslateTransition of JavaFX, but my efforts of trying to switch the code is hopeless..
1'st example (working, and is fading in and out of the fxml screen):
public boolean setScreen(final String name){
if (screens.get(name) != null) { //screen loaded
final DoubleProperty opacity = opacityProperty();
if (!getChildren().isEmpty()) { //if there is more than one screen
Timeline fade = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(opacity, 1.0)),
new KeyFrame(new Duration(2000), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
getChildren().remove(0); //remove the displayed screen
getChildren().add(0, screens.get(name)); //add the screen
Timeline fadeIn = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(opacity, 0.0)),
new KeyFrame(new Duration(2000), new KeyValue(opacity, 1.0)));
fadeIn.play();
}
}, new KeyValue(opacity, 0.0)));
fade.play();
} else {
setOpacity(0.0);
getChildren().add(screens.get(name)); //no one else been displayed, then just show
Timeline fadeIn = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(opacity, 0.0)),
new KeyFrame(new Duration(1000), new KeyValue(opacity, 1.0)));
fadeIn.play();
}
return true;
} else {
System.out.println("screen hasn't been loaded!!! \n");
return false;
}
}
Second example, the TranslateTransition I want to implement instead:
private final double IMG_WIDTH = 500;
private final double IMG_HEIGHT = 500;
private final int NUM_OF_IMGS = 3;
private final int SLIDE_FREQ = 4; // in secs
#Override
public void start(Stage stage) throws Exception {
stage.initStyle(StageStyle.UNDECORATED);
StackPane root = new StackPane();
Pane clipPane = new Pane();
// To center the slide show incase maximized
clipPane.setMaxSize(IMG_WIDTH, IMG_HEIGHT);
clipPane.setClip(new Rectangle(IMG_WIDTH, IMG_HEIGHT));
HBox imgContainer = new HBox();
ImageView imgGreen = new ImageView(new Image(getClass().getResourceAsStream("uib_01.jpg")));
ImageView imgBlue = new ImageView(new Image(getClass().getResourceAsStream("uib_02.jpg")));
ImageView imgRose = new ImageView(new Image(getClass().getResourceAsStream("uib_03.jpg")));
imgContainer.getChildren().addAll(imgGreen, imgBlue, imgRose);
clipPane.getChildren().add(imgContainer);
root.getChildren().add(clipPane);
Scene scene = new Scene(root, IMG_WIDTH, IMG_HEIGHT);
stage.setTitle("Image Slider");
stage.setScene(scene);
startAnimation(imgContainer);
stage.show();
}
private void startAnimation(final HBox hbox) {
EventHandler<ActionEvent> slideAction = (ActionEvent t) -> {
TranslateTransition trans = new TranslateTransition(Duration.seconds(1.5), hbox);
trans.setByX(-IMG_WIDTH);
trans.setInterpolator(Interpolator.EASE_BOTH);
trans.play();
};
EventHandler<ActionEvent> resetAction = (ActionEvent t) -> {
TranslateTransition trans = new TranslateTransition(Duration.seconds(1), hbox);
trans.setByX((NUM_OF_IMGS - 1) * IMG_WIDTH);
trans.setInterpolator(Interpolator.EASE_BOTH);
trans.play();
};
List<KeyFrame> keyFrames = new ArrayList<>();
for (int i = 1; i <= NUM_OF_IMGS; i++) {
if (i == NUM_OF_IMGS) {
keyFrames.add(new KeyFrame(Duration.seconds(i * SLIDE_FREQ), resetAction));
} else {
keyFrames.add(new KeyFrame(Duration.seconds(i * SLIDE_FREQ), slideAction));
}
}
Timeline anim = new Timeline(keyFrames.toArray(new KeyFrame[NUM_OF_IMGS]));
anim.setCycleCount(Timeline.INDEFINITE);
anim.playFromStart();
}
The screen should change on button click. I have this in a separate controller class:
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
public class roomAppController implements Initializable, ScreenController {
private ScreenPane myScreenPane;
#FXML
public ImageView bldArw_1;
public ImageView rmArw_1;
#FXML
private void handleExitButtonEvent(MouseEvent e) {
System.out.println("Button is clicked");
System.exit(0);
}
#FXML
private void handleNextPageEvent(MouseEvent e) {
if((ImageView)e.getSource() == bldArw_1) {
myScreenPane.setScreen("buildingScreen");
}
if((ImageView)e.getSource() == rmArw_1) {
myScreenPane.setScreen("roomScreen");
}
System.out.println("Clicked");
}
#Override
public void initialize(URL location, ResourceBundle resources) {
}
#Override
public void setScreenPane(ScreenPane screenPage) {
myScreenPane = screenPage;
}
}
I have a tree-view with costume TreeCell. tree cell is customized and it looks like below image.
On Right Side I selected the One Tree Cell or Tree item. as you can see there is image-view of hand on left side of each cell. By default it is in black color but i want to replace it with white color icon. as in above mock up.
How can i achieve this????
I want all text and image view icon on selection changed to white color. and last selected tree cell back to normal black color.
My Tree Cell Code is below.
private final class AlertTreeCell extends TreeCell<AlertListItem> {
private Node cell;
private Rectangle rectSeverity;
private Label mIncedentname;
private Label mAlertTitle;
private Label mSentTime;
private Label mSender;
private ImageView ivCategory;
public AlertTreeCell() {
FXMLLoader fxmlLoader = new FXMLLoader(
MainController.class
.getResource("/fxml/alert_list_item.fxml"));
try {
cell = (Node) fxmlLoader.load();
rectSeverity = (Rectangle) cell.lookup("#rectSeverity");
mIncedentname = (Label) cell.lookup("#lblIncidentName");
mAlertTitle = (Label) cell.lookup("#lblAlertTitle");
mSentTime = (Label) cell.lookup("#lblSentTime");
mSender = (Label) cell.lookup("#lblSender");
ivCategory = (ImageView) cell.lookup("#ivCategory");
} catch (IOException ex) {
mLogger.error(ex.getLocalizedMessage(),ex);
}
}
#Override
public void updateItem(AlertListItem item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(null);
mAlertTitle.setText(item.getEvent());
mIncedentname.setText(item.getHeadline());
mSentTime.setText(MyUtils.getListDateFormattedString(item.getReceivedTime()));
mSender.setText(item.getSenderName());
Image image = new Image("/images/ic_cat_" + item.getCategoryIcon().toLowerCase() + "_black.png");
if(image != null){
ivCategory.setImage(image);
}
if(item.getSeverity() != null){
String severityColor = item.getSeverity().toString();
String severityColorCode = null;
if(severityColor != null) {
SeverityColorHelper severityColorHelper = new SeverityColorHelper();
severityColorCode = severityColorHelper.getColorBySeverity(AlertInfo.Severity.fromValue(severityColor));
}
rectSeverity.setFill(Color.web(severityColorCode,1.0) );
}
final AlertTreeCell this$=this;
setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if(event.getClickCount()==1){
Node cell$ = this$.getGraphic();
ImageView ivCategory$ = (ImageView) cell.lookup("#ivCategory");
Image image = new Image("/images/ic_cat_" + item.getCategoryIcon().toLowerCase() + "_white.png");
if(image != null){
ivCategory$.setImage(image);
}
}
}
});
this$.
setGraphic(cell);
}
}
}
problem is that new white icon properly selected and added but how to change back the last selected tree item's image view back to black color icon. actually I have two color images of same type. one is in black color and same image in white color. on selection i want the image and text changed to white colored and all other tree-items in to black color text and black color icon.
I'm not quite sure if the mouse handler is supposed to be changing the icon on selection: if so remove it. Don't use mouse handlers for detecting selection (what if the user navigates through the tree using the keyboard, for example?).
In your constructor, add a listener to the selectedProperty, and change the item accordingly:
public AlertTreeCell() {
FXMLLoader fxmlLoader = new FXMLLoader(
MainController.class
.getResource("/fxml/alert_list_item.fxml"));
try {
cell = (Node) fxmlLoader.load();
rectSeverity = (Rectangle) cell.lookup("#rectSeverity");
mIncedentname = (Label) cell.lookup("#lblIncidentName");
mAlertTitle = (Label) cell.lookup("#lblAlertTitle");
mSentTime = (Label) cell.lookup("#lblSentTime");
mSender = (Label) cell.lookup("#lblSender");
ivCategory = (ImageView) cell.lookup("#ivCategory");
this.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
String col ;
if (isNowSelected) {
col = "_black.png" ;
} else {
col = "_white.png" ;
}
if (getItem() != null) {
Image img = new Image("/images/ic_cat_" + item.getCategoryIcon().toLowerCase() + col);
ivCategory.setImage(img);
}
});
} catch (IOException ex) {
mLogger.error(ex.getLocalizedMessage(),ex);
}
}
In the updateItem(...) method, just check isSelected() and set the image accordingly there, but without the listener.
I have this JavaFX accordion which displays images:
public class Navigation {
private static final Image BLUE_FISH = new Image("/Blue-Fish-icon.png");
private static final Image RED_FISH = new Image("/Red-Fish-icon.png");
private static final Image YELLOW_FISH = new Image("/Yellow-Fish-icon.png");
private static final Image GREEN_FISH = new Image("/Green-Fish-icon.png");
public void initNavigation(Stage primaryStage, Group root, Scene scene) {
VBox stackedTitledPanes = createStackedTitledPanes();
ScrollPane scroll = makeScrollable(stackedTitledPanes);
scroll.getStyleClass().add("stacked-titled-panes-scroll-pane");
scroll.setPrefSize(395, 580);
scroll.setLayoutX(5);
scroll.setLayoutY(32);
//scene = new Scene(scroll);
root.getChildren().add(scroll);
}
private VBox createStackedTitledPanes() {
final VBox stackedTitledPanes = new VBox();
stackedTitledPanes.getChildren().setAll(
createTitledPane("Connections", GREEN_FISH),
createTitledPane("Tables", YELLOW_FISH),
createTitledPane("Description", RED_FISH),
createTitledPane("Blue Fish", BLUE_FISH));
((TitledPane) stackedTitledPanes.getChildren().get(0)).setExpanded(true);
stackedTitledPanes.getStyleClass().add("stacked-titled-panes");
return stackedTitledPanes;
}
public TitledPane createTitledPane(String title, Image... images) {
FlowPane content = new FlowPane();
for (Image image : images) {
ImageView imageView = new ImageView(image);
content.getChildren().add(imageView);
FlowPane.setMargin(imageView, new Insets(10));
}
content.setAlignment(Pos.TOP_CENTER);
TitledPane pane = new TitledPane(title, content);
pane.getStyleClass().add("stacked-titled-pane");
pane.setExpanded(false);
return pane;
}
private ScrollPane makeScrollable(final VBox node) {
final ScrollPane scroll = new ScrollPane();
scroll.setContent(node);
scroll.viewportBoundsProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds) {
node.setPrefWidth(bounds.getWidth());
}
});
return scroll;
}
}
I'm interested is it possible to display rows of data where the images are placed. Something like this:
P.S case example. I have a java object which will be used as list:
public List<dataObj> list = new ArrayList<>();
public class dataObj {
private int connectionId;
private String conenctionname;
private String connectionDescription;
public dataObj() {
}
....................
}
When I insert some data into the Java Array list I want to display it into the accordion based on the above requirement.
P.S 2 In my case what is the proper way to insert text into FlowPane? I tested this:
public TitledPane createTitledPane(String title, Image... images) {
FlowPane content = new FlowPane();
for (Image image : images) {
ImageView imageView = new ImageView(image);
content.getChildren().add(imageView);
FlowPane.setMargin(imageView, new Insets(10));
}
content.setAlignment(Pos.TOP_CENTER);
content.setText("This part will be the first line.\n This part the second.");
TitledPane pane = new TitledPane(title, content);
pane.getStyleClass().add("stacked-titled-pane");
pane.setExpanded(false);
return pane;
}
I get error that inserting text using setText is not correct. What is the proper way?
If you use "\n" the output String will be separated into multiple lines of text.
For example:
component.setText("This part will be the first line.\n This part the second.");
From your update, assuming you have getters and setters:
component.setText(String.valueOf(dataObj.getConnectionId()) + "\n" + dataObj.getConnectionname() + "\n" + dataObj.getConnectionDescription());
You can simply use a ListView:
private void hello() {
ListView<Object> lv = new ListView<>();
// yourList is you List<Object> list
lv.itemsProperty().set(yourList);
lv.setCellFactory(new Callback<ListView<Object>, ListCell<Object>>() {
#Override
public ListCell<Object> call(ListView<Object> p) {
return new youCellFactory();
}
});
AnchorPane content = new AnchorPane();
content.getChildren().add(lv);
// add to TitelPane
TitledPane pane = new TitledPane(title, content);
}
static class youCellFactory extends ListCell<Object> {
#Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.getConenctionname());
}
}
}
I have not tested this code but it should work.
Here is an nice Example too, but without object:
ListViewSample.java