How to display number of lines textarea javafx - javafx

I´m trying to create a list with the number of lines of a textarea like in a text editor. I have done it with a VBox item and adding TextField ListCell but when I scroll in the textarea, the VBox doesn´t it . How can I do it?. This is part of code:
TextArea areaNueva = new TextArea();
areas.add(numeroTab, areaNueva);
areas.get(numeroTab).setStyle("-fx-font:15pt \"Times New Roman\";" + "-fx-focus-color: transparent;");
BorderPane bor = new BorderPane();
ObservableList<TextFieldListCell> tf = FXCollections.observableArrayList();
TextFieldListCell cell = new TextFieldListCell();
VBox b = new VBox();
cell.setPrefSize(20,1);
cell.setFont(Font.font("Times New Roman",11.35));
cell.setText("1");
tf.add(0,cell);
b.getChildren().addAll(tf);
b.setSpacing(-2);
b.setPadding(new Insets(3,0,0,0));
bor.setLeft(b);
bor.setCenter(areaNueva);
Tab tabNuevo = new Tab("Sin Titulo");
tabs.add(numeroTab, tabNuevo);
tabs.get(numeroTab).setClosable(true);
tabs.get(numeroTab).setContent(bor);
An with this I add new number of lines:
private ArrayList<ObservableList<TextFieldListCell>> lineas = new ArrayList<ObservableList<TextFieldListCell>>();
String parte = null;
int i = 1;
while ((parte = br.readLine()) != null) {
areaAUtilizar.appendText(parte + "\n");
if(i!=1){
TextFieldListCell c = new TextFieldListCell();
c.setText(Integer.toString(i));
c.setFont(Font.font("Times New Roman",11.35));
c.setPrefSize(20, 13);
lineas.get(a).add(i-1,c);
boxes.get(a).getChildren().setAll(lineas.get(a));
}
i++;
}

I solved it by removing the scroll of the textarea and the listview and put its opacity to 0, and putting both in a borderpane. After I put a scrollbar and the borderpane in a scrollpane. And for it to appear the scrollbar of the scrollpane I increased the height of the textarea and the listview when the lines of the textarea are more great than the prefheight.

Related

JavaFX fit an image in a toggleButton

I have the following code
Image img = new Image(getClass().getResource("1.png").toExternalForm(), tg.getWidth(), tg.getHeight(), false, true, true);
ImageView view = new ImageView(img);
tg.setGraphic(view);
(where tg is a toggle button)
and I get this
I want the image to fit perfectly into the button but whatever I do I'm unable to accomplish this. I've already tried using view.setFit methods but it doesn't seem to have any effect
Edit:
This is the code that creates the GridPane
this.gameBoard = new GridPane();
this.gameBoard.setPrefSize(600, 600);
this.gameCards = new ToggleButton[this.boardSize * this.boardSize];
EventHandler<ActionEvent> cardSelectedHandler = this::onCardSelected;
for (int i = 0; i < this.gameCards.length; i++) {
this.gameCards[i] = new ToggleButton;
this.gameCards[i].setPrefSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE);
this.gameCards[i].setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
this.gameCards[i].setOnAction(cardSelectedHandler);
this.gameBoard.add(this.gameCards[i], i % this.boardSize, i / this.boardSize);
GridPane.setHgrow(this.gameCards[i], Priority.ALWAYS);
GridPane.setVgrow(this.gameCards[i], Priority.ALWAYS);
}
private void onCardSelected(ActionEvent event) {
ToggleButton tg = (ToggleButton) event.getTarget();
Image img = new Image(getClass().getResource("1.png").toExternalForm(), tg.getWidth(), tg.getHeight(), false, true, true);
ImageView view = new ImageView(img);
tg.setGraphic(view);
EDIT 2:
doing some change
private void onCardSelected(ActionEvent event) {
ToggleButton tg = (ToggleButton) event.getTarget();
Image img = new Image(getClass().getResource("1.png").toExternalForm());
ImageView view = new ImageView(img);
view.setFitHeight(150);
view.setFitWidth(150);
view.setPreserveRatio(false);
tg.setAlignment(Pos.TOP_LEFT);
tg.setGraphic(view);
I now get
but I still get this button resize

VBox .getHeight() Not Changing until after .setOnAction Finishes [duplicate]

This question already has answers here:
Get the height of a node in JavaFX (generate a layout pass)
(2 answers)
Closed 3 years ago.
So I'm not sure how to calculate the height of the node during the .setOnAction event I have tried .requestLayout()/.applyCss() not sure what else to try I am trying to find the height of the vBox after adding a node but it is only printing the height of the node before the new one was added
public class Main extends Application {
#Override
public void start(Stage stage) {
VBox vBoxContainer = new VBox();
vBoxContainer.setAlignment(Pos.CENTER);
vBoxContainer.setPrefSize(200,200);
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
for (int i = 0; i < 5; i++)
vBox.getChildren().add(new Label("newLabel"));
vBoxContainer.getChildren().add(vBox);
Button button = new Button("Add Label");
button.setOnAction(event -> {
System.out.println("Height Before new Label:"+vBox.getHeight());
vBox.getChildren().add(new Label("newLabel"));
//here is where I was adding code to produce expected result
System.out.println("Height After new Label:"+vBox.getHeight());
});
Button checkButton = new Button("Print VBox Height");
checkButton.setOnAction(event -> System.out.println("VBox Height:"+vBox.getHeight()));
vBoxContainer.getChildren().addAll(button, checkButton);
stage.setScene(new Scene(vBoxContainer));
stage.show();
}
}
Run the example and Click the button that adds a Label to the vBox and it outputs
Actual Result:
Height Before new Label:85.0
Height After new Label:85.0
Expected Result:
Height Before new Label:85.0
Height After new Label:102.0
But if you then click the Print VBox Height Button it will show the correct height of:
VBox Height:102.0
You can try adding a listener to the VBox's height property.
VBox vBoxContainer = new VBox();
vBoxContainer.setAlignment(Pos.CENTER);
vBoxContainer.setPrefSize(200, 200);
VBox vBox = new VBox();
vBox.setAlignment(Pos.CENTER);
vBoxContainer.getChildren().add(vBox);
vBox.heightProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Height changed to: " + newValue.doubleValue());
if(newValue.doubleValue() > 100)
{
//do something!
}
});
for (int i = 0; i < 5; i++) {
vBox.getChildren().add(new Label("newLabel"));
}
Button button = new Button("Add Label");
button.setOnAction(event -> {
vBox.getChildren().add(new Label("newLabel"));
});
Button checkButton = new Button("Print VBox Height");
checkButton.setOnAction(event -> System.out.println("VBox Height:" + vBox.getHeight()));
vBoxContainer.getChildren().addAll(button, checkButton);
stage.setScene(new Scene(vBoxContainer));
stage.show();
requestLayout does not actually do a layout pass. It simply tells JavaFX, that a layout pass is required which will result in JavaFX doing the layout pass some time after your method returns. To do the layout yourself, you need to call layout yourself, i.e. change the logic in the event handler like this:
button.setOnAction(event -> {
System.out.println("Height Before new Label:"+vBox.getHeight());
vBox.getChildren().add(new Label("newLabel"));
// manually doing layout on the root here
vBoxContainer.applyCss();
vBoxContainer.layout();
System.out.println("Height After new Label:"+vBox.getHeight());
});
Note that I do the layout pass for the root, since the ancestor layouts can also be involved in determining the actual size of a Node...

JavaFX Layout complie time

I'm trying to achieve this but I'm running into some problems. I got the rough skeleton, but for example when I try to add the output TextArea to my Vbox container, I get an error.
The error is: The method addAll(int, Collection<? extends Node>) in the type List<Node> is not applicable for the arguments (HBox, HBox, HBox, Button, TextArea)
EDIT: I had the wrong import for the TextArea, I had the awt instead of the javafx.scene.control.TextArea;
GridPane g1 = new GridPane();
HBox firstRow = new HBox();
firstRow.setPadding(new Insets(10));
Label name = new Label("Name: ");
TextField nameInput = new TextField();
g1.add(name, 0, 0);
g1.add(nameInput, 1, 0);
firstRow.getChildren().addAll(g1);
GridPane g2 = new GridPane();
HBox secondRow = new HBox();
secondRow.setPadding(new Insets(10));
Label city = new Label("City: ");
TextField cityInput = new TextField();
g2.add(city, 0, 0);
g2.add(cityInput, 1, 0);
secondRow.getChildren().addAll(g2);
HBox thirdRow = new HBox();
thirdRow.setSpacing(20);
thirdRow.setPadding(new Insets(5));
RadioButton radioName = new RadioButton("Name");
RadioButton radioCity = new RadioButton("City");
RadioButton radioZip = new RadioButton("Zip");
ToggleGroup group = new ToggleGroup();
radioName.setToggleGroup(group);
radioCity.setToggleGroup(group);
radioZip.setToggleGroup(group);
thirdRow.getChildren().addAll(radioName, radioCity, radioZip);
Button search = new Button("Search");
HBox fifthRow = new HBox();
TextArea output = new TextArea();
VBox container = new VBox();
container.getChildren().addAll(firstRow, secondRow, thirdRow, search);
Your question wasn't too clear initially because you did not include the error you saw. The problem is because you have imported the wrong TextArea, which import statements are also not included in your question.
You need to change import java.awt.TextArea; into import javafx.scene.control.TextArea;. The former is a control for AWT, while the latter is the control for JavaFX.
As it says, you need to add a child "ouput" which is TextBox element to a container.
container.getChildren().addAll(firstRow, secondRow, thirdRow, search, output);
Aslo I would like to note that you need to arrange elements in proper order, as this code is not pragmatic at all.

Gluon Mobile Toggle Button Jumping

I'm trying to implement a Gluon Mobile toggle button for a survey page, and when testing, the button jumps to the left a little when I click it. I don't want it to jump at all. You can see it here:
Relevant code is here:
StackPane getToggler() {
ToggleButton toggleButton = new ToggleButton("Yes");
ToggleButtonGroup toggleButtonGroup = new ToggleButtonGroup();
toggleButtonGroup.setSelectionType(SelectionMode.SINGLE);
toggleButtonGroup.setPadding(new Insets(10));
toggleButton = new ToggleButton("Yes");
toggleButton.setStyle("-fx-text-fill:steelblue;");
toggleButton.setUserData("1");
toggleButton.setSelected(false);
toggleButton.selectedProperty().addListener((obv, ov, nv) -> {
if (nv.booleanValue()) {
toggleButtonGroup.setUserData("1");
}
});
toggleButtonGroup.getToggles().add(toggleButton);
toggleButton = new ToggleButton("No");
toggleButton.setStyle("-fx-text-fill:steelblue;");
toggleButton.setSelected(true);
toggleButton.setUserData("0");
toggleButton.setSelected(false);
toggleButton.selectedProperty().addListener((obv, ov, nv) -> {
if (nv.booleanValue()) {
toggleButtonGroup.setUserData("0");
}
});
toggleButtonGroup.getToggles().add(toggleButton);
togglers.add(toggleButtonGroup);
StackPane wrapper = new StackPane();
wrapper.setAlignment(Pos.CENTER);
wrapper.getChildren().add(toggleButtonGroup);
return wrapper;
}
Here's where I get the togglers and their relation to the label to the left:
for (int i = 0; i < this.questions.length; i++) {
HBox row = new HBox();
row.setSpacing(5);
row.setAlignment(Pos.CENTER_LEFT);
Label label = new Label(this.questions[i]);
label.setWrapText(true);
label.setPrefWidth(200);
label.setTextAlignment(TextAlignment.LEFT);
label.setFont(new Font("System", 14));
StackPane wrapper = this.getToggler();
Region region = new Region();
HBox.setHgrow(region, Priority.ALWAYS);
HBox.setHgrow(label, Priority.NEVER);
row.getChildren().addAll(label,region,wrapper);
box.getChildren().add(row);
box.getChildren().add(new Separator());
}
After some debugging, I've realized that the min width value of the toggle buttons is wider than their pref width.
This means that after the user selects one toggle, the min width is applied, and the control is resized with the required min width, shrinking the region as a consequence.
A quick fix (until this gets fixed in the control) can be setting the min width of your toggle buttons:
private StackPane getToggler() {
ToggleButtonGroup toggleButtonGroup = new ToggleButtonGroup();
ToggleButton toggleButtonYes = new ToggleButton("Yes");
toggleButtonYes.minWidthProperty().bind(toggleButtonYes.prefWidthProperty());
toggleButtonGroup.getToggles().add(toggleButtonYes);
ToggleButton toggleButtonNo = new ToggleButton("No");
toggleButtonNo.minWidthProperty().bind(toggleButtonNo.prefWidthProperty());
toggleButtonGroup.getToggles().add(toggleButtonNo);
...;
}

Make portion of a text bold in a JavaFx Label or Text

In my JavaFx application I need to have a word or two rendered in boldface in the whole sentence. Currently the sentence is rendered as a JavaFx Label but upgrading component also would not allow me set the text as so that I can have the words "Sample" displayed in bold.
String s = "This is a <b>Sample</b> sentence"
Label label = new Label(s);
output
This is a Sample sentence
JavaFx Text also does not allow this. Is there any component where I can have a portion of the text in boldface?
I am not sure if JavaFx WebView is a good idea for rendering many small sentences in a window.
It is possible to use TextFlow container from JavaFX8.
Then you can easily add differently styled Text nodes inside it.
TextFlow flow = new TextFlow();
Text text1=new Text("Some Text");
text1.setStyle("-fx-font-weight: bold");
Text text2=new Text("Some Text");
text2.setStyle("-fx-font-weight: regular");
flow.getChildren().addAll(text1, text2);
TextFlow container will automatically wrap content Text nodes.
Since the previous answers did not include FXML code, I'll post an additional one.
As suggested by #Ernisto, you can use a TextFlow that contains Text parts, where each part can be styled differently.
Example FXML file content:
<TextFlow>
<Text text="Normal text and "/>
<Text text="bold text and " style="-fx-font-weight: bold"/>
<Text text="italic text and " style="-fx-font-style: italic"/>
<Text text="red text." style="-fx-stroke: red"/>
</TextFlow>
Output:
Update: JavaFX 8 provides new control for the rich text: TextFlow
Unfortunately there is no such feature in 2.2, although it may be included into next release.
For now you can try to use next approaches:
HBox with several Label or Text components
WebView
Canvas with several Text components drawn
public class UtilsDialog {
private static final String TAG = "UtilsDialog";
private static boolean sIsShowing = false;
public static void showDialogShowError(String title, String msg, String defaultStyle,
#Nullable String customStyle, String... styledWords) {
if (sIsShowing) return;
Stage dialogStage = new Stage(StageStyle.UTILITY);
dialogStage.initModality(Modality.APPLICATION_MODAL);
dialogStage.setWidth(400);
dialogStage.setHeight(220);
BorderPane borderPane = new BorderPane();
borderPane.setPadding(new Insets(15));
borderPane.setPrefWidth(Integer.MAX_VALUE);
borderPane.setPrefHeight(Integer.MAX_VALUE);
Scene scene = new Scene(borderPane);
dialogStage.setScene(scene);
sIsShowing = true;
dialogStage.show();
UtilsGui.closeOnEsc(borderPane, scene);
scene.addEventHandler(KeyEvent.KEY_PRESSED, t -> {
if (t.getCode() == KeyCode.ESCAPE) {
sIsShowing = false;
}
});
// Top
Text textTitle = new Text(title);
textTitle.setStyle("-fx-font-size: 18px;");
HBox hBoxTop = new HBox(10);
hBoxTop.getChildren().addAll(textTitle);
borderPane.setTop(hBoxTop);
// Center
TextFlow textFlow = new TextFlow();
List<String> words = Arrays.asList(msg.split(" "));
List<String> styledWordsList = Arrays.asList(styledWords);
for (String word : words) {
Text tmpWord = new Text(word);
if (styledWordsList.contains(word
.replace(".", "")
.replace(",", "")
.replace("?", "")
.replace("!", "")
.replace(";", "")
.replace("\n", "")
)) {
tmpWord.setStyle(customStyle);
} else {
if (defaultStyle == null) {
tmpWord.setStyle("");
} else {
tmpWord.setStyle(defaultStyle);
}
}
tmpWord.setText(tmpWord.getText());
textFlow.getChildren().add(tmpWord);
textFlow.getChildren().add(new Text(" "));
}
Text textMsg = new Text(msg);
textMsg.setStyle("-fx-font-size: 14px;");
HBox hBoxInputPane = new HBox(10);
hBoxInputPane.setAlignment(Pos.CENTER);
VBox vBoxCenter = new VBox(10);
vBoxCenter.setPadding(new Insets(25, 0, 15, 0));
vBoxCenter.getChildren().addAll(textFlow);
borderPane.setCenter(vBoxCenter);
JFXButton btnOk = new JFXButton("OK");
btnOk.setAlignment(Pos.CENTER_RIGHT);
btnOk.setStyle("-fx-text-fill: WHITE; -fx-background-color: #5264AE; -fx-font-size: 14px;");
btnOk.setOnAction(event -> {
sIsShowing = false;
dialogStage.close();
});
// Bottom
HBox hBoxBottom = new HBox();
final Pane spacer = new Pane();
HBox.setHgrow(spacer, Priority.ALWAYS);
hBoxBottom.getChildren().addAll(spacer, btnOk);
borderPane.setBottom(hBoxBottom);
// store on close
dialogStage.setOnCloseRequest(event -> sIsShowing = false);
}
}
call:
UtilsDialog.showDialogShowError("Test", "This is the message to show. Does it work?",
null, "-fx-font-weight: bold", "This", "message", "show");

Resources