How to add children to ScrollPane - javafx

Now, I've looked around for a while, but I haven't found anything that helps me. I'm trying to create a chat-based game, which utilizes JavaFX-FXML and relies on a ScrollPane.
I'm trying to create JLabels and add them to the ScrollPane dynamically.
With my own research I found that you can't set multiple children for a ScrollPane; you have to use the setContent method and have a pane to add the children inside of that, so that's what I did but I still get an error when adding the labels. It's inside the IDE and tells me I have to use a Node but I don't know what a node is.
Here's my controller:
public class Controller() {
import javax.swing.*;
import javafx.fxml.FXML;
import javafx.scene.input.*;
import javafx.scene.layout.Pane;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import static jdk.nashorn.internal.objects.NativeError.printStackTrace;
private String msg;
private char[] msgA;
#FXML
private Label opt1;
#FXML
private Label opt2;
#FXML
private Label opt3;
#FXML
private TextField msgBox;
#FXML
private AnchorPane gameUI;
#FXML
private AnchorPane mainMenu;
#FXML public ScrollPane labelPane;
private boolean optionSelected = false;
private void startup(){
System.out.println("startup called! Getting player's name now..");
String mcName=JOptionPane.showInputDialog(null,"Please enter your name");
System.out.println(mcName+" was inputted, let's hope it's an appropriate name! Haha!");
JLabel label = new JLabel();
label.setName("evieHi");
label.setText("Hi "+mcName+"! How are you doing?");
labelPane.setContent(p);
opt1.setText("I'm good, how are you?");
opt2.setText("Not so well until you texted. ;D");
opt3.setText("I'm sorry, who is this?");
Pane p = new Pane();
p.getChildren().add(label);
}
}
I do realize some of the imports and variables are redundant. They're not relevant to my question so I left the methods using them out of my code I included.
Thanks in advance and I'm sorry you had to read my messy code.

Attempting to create a Swing UI component doesn't bode well with JavaFX...
I fixed it with the help of #James_D and #fabian pointing out what I'm to dumb to realize..
private void startup(){
System.out.println("startup called! Getting player's name now..");
mcName=JOptionPane.showInputDialog(null,"Please enter your name");
System.out.println(mcName+" was inputted,let's hope it's an appropriate name! Haha!");
Label label = new Label();
label.setText("Hi "+mcName+"! How are you doing?");
p.getChildren().add(label);
labelPane.setContent(p);
}

Related

ComboBox does not populate with observable array list (JavaFX) [duplicate]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I will be very grateful for your help, I am trying to create JavaFX applications, I want to start creating something on the canvas panel, the code is compiling but no effects, it seems to me that the canvas panel view is not refreshed, maybe some spec will advise what I forgot, I throw in the whole class, below the code the window structure from the scene builder and the project structure.
[![package com.example.rpgfxmaven;
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.AnchorPane;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.IOException;
public class GameControler{
final int oryginalnyRozmiarLudzika = 16; // 16x16 tile
final int skala = 3;
final int rozmiarLudzika = skala * oryginalnyRozmiarLudzika;
final int dlugoscPlanszy = 20;
final int szerokoscPlanszy = 15;
final int dlugoscEkranu = rozmiarLudzika*dlugoscPlanszy;
final int szerokoscEkranu = rozmiarLudzika*szerokoscPlanszy;
#FXML
private Canvas canvaspane = new Canvas(dlugoscEkranu, szerokoscEkranu);
GraphicsContext content;
public static MediaPlayer mediaPlayer;
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("maingame-window.fxml"));
AnchorPane anchorPane= loader.load();
anchorPane.setPrefSize(dlugoscEkranu+100, szerokoscEkranu+75);
Scene scene = new Scene(anchorPane);
primaryStage.setScene(scene);
primaryStage.show();
content = canvaspane.getGraphicsContext2D();
startGame();
}
public void startGame()
{
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(10), e ->run(content)));
timeline.setCycleCount(Timeline.INDEFINITE);
}
public void run(GraphicsContext content) {
content.setFill(Color.BLUE);
content.fillRect(100, 100, rozmiarLudzika,rozmiarLudzika);
}
}
This is wrong:
#FXML
private Canvas canvaspane = new Canvas(dlugoscEkranu, szerokoscEkranu);
You should never set an #FXML injected field to a new value.
The fxml loader will already have created an instance of the #FXML field and linked that into the object tree returned by the loader.
If you assign the field to a new value, the new value will not be in the loaded object tree added to the scene graph, so it will never be seen. Only the empty canvas created by the loader will be seen.
You almost definitely have other issues with your application outside of this, but I can't really outline them in detail here.

TableView: Populating editable TextField container

After many hours of reading and trying I have been struggling with populating editable TextField containers within a TableView.
I already managed to display data from an ObservableList of a custom object to my TableView instance.
I already tried this command:
spalteTag.setCellFactory(TextFieldTableCell.forTableColumn(spalteTag));
But this gives an error whereas this type of code
spalteIstErledigt.setCellFactory(CheckBoxTableCell.forTableColumn(spalteIstErledigt));
works properly.
package sample;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.NumberStringConverter;
import tabellen.MysqlController;
import tabellen.TabelleKabelzug;
public class mainController {
ObservableList<TabelleKabelzug> oListeKabelzug = FXCollections.observableArrayList();
#FXML
private TableView tableViewKabelzug = new TableView();
#FXML
private TableColumn<TabelleKabelzug, Integer> spalteId = new TableColumn();
#FXML
private TableColumn<TabelleKabelzug, Boolean> spalteIstErledigt = new TableColumn();
#FXML
private TableColumn<TabelleKabelzug, String> spalteTag = new TableColumn();
public void initialize() {
initialisiereKabelzugliste();
tableViewKabelzug.setItems(oListeKabelzug);
}
public void initialisiereKabelzugliste() {
MysqlController controller = new MysqlController();
controller.mitMysqlVerbinden();
oListeKabelzug.setAll(controller.kabelzuglisteLaden());
spalteIstErledigt.setCellFactory(CheckBoxTableCell.forTableColumn(spalteIstErledigt));
spalteTag.setCellFactory(TextFieldTableCell.forTableColumn(spalteTag));
tableViewKabelzug.setItems(oListeKabelzug);
}
}
Example of my TableColumn "spalteTag" within my .fxml-File:
<TableColumn fx:id="spalteTag" text="BMK">
<cellValueFactory>
<PropertyValueFactory property="tag" />
</cellValueFactory>
<cellFactory>
??? <-- Any code in here possible?
</cellFactory>
</TableColumn>
Here is a sample of what it looks like at the moment (without any errors of course):
TableView with populated data and Checkboxes
So my 3 questions now are:
First how can I add TextFields in every TableView cell that is dedicated to a String value?
Second how can I make these TextFields editable for every TableView cell?
Third and is there any setup possible for this in my .fxml file? (this would be the most convenient solution to me)
Greetings from Germany :)
You don't have to pass parameter to forTableColumn function.
Try this
spalteTag.setCellFactory(TextFieldTableCell.forTableColumn());

How to recognize Node bounds change in Scene?

Lets say I have some TextField which is placed deep in the panes layout structure. I want add listener or recognize in some way that TextField changed its position (x, y) in Scene. The question is - how can I achive it in a proper, reusable way?
I provide some test code. To recreate please drag stage border, which will cause TextField position change.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
TextField textField = new TextField();
Button button = new Button("Button");
HBox hBox = new HBox(textField, button);
hBox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
StackPane stackPane = new StackPane(hBox);
stackPane.setPrefSize(600., 400.);
Scene scene = new Scene(stackPane);
stage.setScene(scene);
stage.show();
}
}
Add a listener to the localToSceneTransform property of the node.
node.localToSceneTransformProperty().addListener((o, oldValue, newValue) -> {
System.out.println("transform may have changed");
});
Note that this
Yields some "false positives", i.e. it may notify you, if the position hasn't actually changed.
Registering too many of those listeners to nodes may decrease the performance of your application, since doing so involves listening to changes for all nodes in the hierarchy up to the root node.
In addition to this a listener to the boundsInLocal property may be needed, if you also want to be notified to the size of the node itself changing.

Java FX TextField blur

Can anyone tell me why sometimes JavaFX displays the content of a TextField with a blur effect on it? It seems to be random and occurs in any of my TextFields. Please see the image attached.
Focusing on the intermittent rendering artifact mentioned here, the 2 glyph looks like it's been rendered twice, with one copy shifted horizontally relative to the other. Such apparently random anomalies are notoriously difficult to identify. Myriad causes may include incorrect synchronization, improper layout, defects in the host platform's rendering pipeline, etc. For reference, the example below may allow you to test on disparate platforms.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* #see https://stackoverflow.com/a/53989899/230513
*/
public class TextFieldTest extends Application {
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("TextFieldTest");
BorderPane root = new BorderPane();
root.setCenter(createContent());
root.setBottom(createVersion());
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
private Node createContent() {
HBox row1 = new HBox(4);
Label channelsLabel = new Label("Channels:");
TextField channelsText = new TextField("2");
channelsText.setPrefWidth(32);
Label separatorLabel = new Label("Separator:");
TextField separatorText = new TextField("!");
separatorText.setPrefWidth(32);
row1.setPadding(new Insets(8));
row1.getChildren().addAll(
channelsLabel, channelsText, separatorLabel, separatorText);
HBox row2 = new HBox(4, new Label("Label:"), new TextField());
row2.setPadding(new Insets(8));
return new VBox(row1, row2);
}
private Label createVersion() {
Label label = new Label(
System.getProperty("os.name") + " v"
+ System.getProperty("os.version") + "; Java v"
+ System.getProperty("java.version"));
label.setPadding(new Insets(8));
return label;
}
public static void main(String[] args) {
launch(args);
}
}
As shown in the Modena example, an intentional blur effect indicates that the text field is focused:
The detail that gives rise to the blurred effect in your image is a compound border, seen below at 2x:
Comparable effects are seen here for buttons (top row) and default buttons (bottom row):

remove default focus from TextField JavaFX

I have designed some TextField in a form by SceneBuilder, when I run the code, one of the TextFields has been clicked by default, I want when I run the code, none of the TextFields get selected by default and user select a TextFiled.
UPDATE: As you see in this image I want to make the first field like other two field when code runs(no curser in field)
How can I do this?
In my case the accepted answer is not working. But this worked:
i requested focus for parent wrapped in runLater.
#FXML
public void initialize() {
//unfocus pathField
Platform.runLater( () -> root.requestFocus() );
}
Direct call of requestFocuss does not work.
Had the same problem with a non - editable TextField, which got selected and highlighted every time.
Solved it by setting myTextField.setFocusTraversable(false);
Note that in this case the focus goes to the next UI element an you must set every single element you don't want focused. You lose also the ability to select the element via the Tab key.
The ApiDoc states that setFocusTraversable() is false by default, but that seems not to work, unless explicitly called.
As there is no public method to achieve this, there is no direct way. Though, you can use a trick to do it. You can have a BooleanProperty just to check when the control is focused for the first time. Listen to focusProperty() of the control and when it is focused for the first time, delegate the focus to its container. For the rest of the focus, it will work as it should.
Example:
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final BooleanProperty firstTime = new SimpleBooleanProperty(true); // Variable to store the focus on stage load
VBox vBox = new VBox(10);
vBox.setPadding(new Insets(20));
TextField t1 = new TextField();
TextField t2 = new TextField();
TextField t3 = new TextField();
t1.setPromptText("FirstName");
t2.setPromptText("LastName");
t3.setPromptText("Email");
vBox.getChildren().addAll(new HBox(t1, t2), t3);
primaryStage.setScene(new Scene(vBox, 300, 300));
primaryStage.show();
t1.focusedProperty().addListener((observable, oldValue, newValue) -> {
if(newValue && firstTime.get()){
vBox.requestFocus(); // Delegate the focus to container
firstTime.setValue(false); // Variable value changed for future references
}
});
}
public static void main(String[] args) {
launch(args);
}
}
On initial screen load :
You can simply set the focus traversable to false in the initialize method. Here is an example:
#Override
public void initialize(URL location, ResourceBundle resources) {
yourTextField.setFocusTraversable(false);
}
You can simply use Bindings
TextField textField = new TextField();
textField.styleProperty().bind(
Bindings
.when(textField.focusedProperty())
.then("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);")
.otherwise("-fx-prompt-text-fill: derive(-fx-control-inner-background, -30%);"));
This will keep your prompt text visible even when the TextField is focused, as long it's empty.

Resources