I am currently working on an assignment in which I need to make an application that has two buttons: read/write, and a textArea with a gray background and blue text, that will display the read content of a file that is written to on button press. I have to save an array of 5 numbers, the date, and a double (2.5).
I have gotten to the point of getting everything to work except for the appending of the text to the textArea... no matter where I seem to pass the value it gives me an error or tells me that it doesn't exist as a variable!
My question is: How do I get the values that I have read from the file to update the text in the textArea instead of just console?
Here is my first file which will create the application and populate the scene. The buttons and text area are all the correct color.
package chapter17;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.io.IOException;
import javafx.scene.layout.Region;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
public class Exercise17_5 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setAlignment(Pos.CENTER);
Button write = new Button("Write");
Button read = new Button("Read");
TextArea readText = new TextArea("This is text testing...");
readText.setPrefColumnCount(15);
readText.setPrefRowCount(5);
readText.setWrapText(true);
readText.setStyle("-fx-text-fill: blue");
//readText.setStyle("-fx-background-color: grey");
readText.setFont(Font.font("Times", 20));
hBox.getChildren().addAll(write, read, readText);
ReadWrite readWriting = new ReadWrite();
write.setOnAction(e -> {
try {
readWriting.write();
}
catch (IOException excepiton) {
excepiton.printStackTrace();
}});
read.setOnAction(e -> {
try {
readWriting.read();
}
catch (IOException exception){
exception.printStackTrace();
}
});
Scene scene = new Scene(hBox,550,550);
primaryStage.setScene(scene);
primaryStage.setTitle("Exercise 17.5");
primaryStage.show();
Region region = (Region) readText.lookup(".content");
region.setStyle("-fx-background-color: gray");
}
}
Here is the second file that will contain the read and write methods, and the variables that store what is read. I can get them to print out to console as demonstrated below. They need to be appended to my already existing textArea readText.
package chapter17;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
public class ReadWrite extends Exercise17_5 {
int[] numbers = {1, 2, 3, 4, 5};
public ReadWrite(){
};
public void write() throws IOException {
try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Exercise17_5.dat"))){
output.writeObject(numbers);
output.writeObject(new Date());
output.writeDouble(2.5);
}
catch (IOException exception) {
exception.printStackTrace();
}
}
public void read() throws IOException {
try{
FileInputStream inputFile = new FileInputStream("Exercise17_5.dat");
ObjectInputStream input = new ObjectInputStream(inputFile);
int[] numbers = (int[])(input.readObject());
java.util.Date date = (java.util.Date)(input.readObject());
double decimal = (double)(input.readDouble());
for (int i = 0; i < numbers.length; i++){
System.out.print(numbers[i] + " ");
}
System.out.println();
System.out.println(decimal);
System.out.println(date);
input.close();
}
catch (IOException | ClassNotFoundException exception2){
exception2.printStackTrace();
}
}
}
Related
I'm new to JavaFX. I try to program a simple GUI but I face those problem whom might be related.
I set files with a File Chooser and want to do pretty basic operations:
save the last folder used
write the name of the selected file in the VBox
Here's my code (which compiles):
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
public static Stage primaryStageS;
public static Scene mainScene;
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene((new Test(primaryStage).getScene()));
primaryStageS = primaryStage;
primaryStage.setTitle("Parcel Manager Main Page");
primaryStage.initStyle(StageStyle.DECORATED);
VBox main = new VBox(new Label("Test program"));
mainScene = new Scene(main, 800, 600);
primaryStage.setScene((new Test(primaryStage)).getScene());
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
public class Object1 {
String name;
public Object1(File f) throws IOException {
name = f.getName();
}
public String getName() {
return name;
}
}
public class Test {
Object1 collec;
String collecName;
File lastFolder;
Pane rootGroup;
public Test(Stage stage) {
setButtons(stage);
}
public void setButtons(Stage stageGoal) {
VBox vbox = new VBox();
Button b = getButton(stageGoal);
vbox.getChildren().addAll(b, new Label(getCollecName() == null ? "no name" : collecName));
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(vbox, 0, 0);
inputGridPane.getChildren().addAll(vbox);
rootGroup = new VBox(12);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12, 12, 12, 12));
}
public Button getButton(Stage stage) {
FileChooser fileChooserParcel = new FileChooser();
fileChooserParcel.setInitialDirectory(getLastFolder());
Button button = new Button("Select a File");
button.setOnAction(e -> {
File f = fileChooserParcel.showOpenDialog(stage);
if (f != null) {
try {
collec = new Object1(f);
} catch (IOException e1) {
e1.printStackTrace();
}
setLastFolder(f.getParentFile());
setCollecName(collec);
setButtons(stage); // tried to reload every buttons - doesn't work
stage.setWidth(stage.getWidth() + 0.0001); // found this dirty hack but doesn't work
}
});
return button;
}
public void setCollecName(Object1 o1) {
collecName = o1.getName();
}
public String getCollecName() {
return collecName;
}
public File getLastFolder() {
return lastFolder;
}
public void setLastFolder(File folder) {
System.out.println("set last folder: " + folder);
lastFolder = folder;
}
private Scene getScene() {
return new Scene(rootGroup, 800, 600);
}
}
}
I cannot refresh the Nodes, either to set a current Initial Directory or display the collecName on the VBox. I tried to regenerate them with reloading of objects or resizing the window, but nothing works. When I print the variables on console, I see that they changes. But haven't found any refresh method for any of my objects.
I bet it's a design program issue, but I have been moving things around for the last week and doesn't know how to fix this.
Thanks !
You are only setting the initial directory once. I guess you want to set it every time you click the button. So move that line of code to inside the handler.
Compare the below getButton() method with yours.
public Button getButton(Stage stage) {
FileChooser fileChooserParcel = new FileChooser();
Button button = new Button("Select a File");
button.setOnAction(e -> {
fileChooserParcel.setInitialDirectory(getLastFolder()); // CHANGE HERE.
File f = fileChooserParcel.showOpenDialog(stage);
if (f != null) {
try {
collec = new Object1(f);
} catch (IOException e1) {
e1.printStackTrace();
}
setLastFolder(f.getParentFile());
setCollecName(collec);
setButtons(stage); // tried to reload every buttons - doesn't work
stage.setWidth(stage.getWidth() + 0.0001); // found this dirty hack but doesn't work
}
});
return button;
}
import java.io.File;
import java.util.Scanner;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class ShakespeareUI extends Application {
public String Quotes(String fileName) throws Exception{
File file = new File (fileName);
String line ="";
Scanner sc = new Scanner(file);
while(sc.hasNextLine()){
line+= sc.nextLine();
}
return line;
}
#Override // Override the start method in the Application class
public void start(Stage primaryStage)throws Exception {
BorderPane pane = new BorderPane();
// Top of Pane with Text
Pane paneForText = new Pane();
paneForText.setPadding(new Insets(0,0,5,0));
Text shText = new Text(25, 50,"Shakespeare Quotes");
shText.setFont(Font.font("Arial", 28));
paneForText.getChildren().add(shText);
pane.setTop(paneForText);
// Center of Border Pane with TextArea
TextArea taQuote = new TextArea();
taQuote.setPrefColumnCount(30);
taQuote.setPrefRowCount(5);
pane.setCenter(taQuote);
// Bottom of Pane with Buttons
HBox paneForButtons = new HBox(20);
Button btLear = new Button("King Lear");
Button btMacBeth = new Button("MacBeth");
Button btHamlet = new Button("Hamlet");
Button btRichard = new Button("Richard III");
Button btOthello = new Button("Othello");
pane.setBottom(paneForButtons);
paneForButtons.getChildren().addAll(btLear, btMacBeth, btHamlet, btRichard, btOthello );
paneForButtons.setAlignment(Pos.CENTER);
paneForButtons.setStyle("-fx-border-color: green");
// Create a scene and place it in the stage
Scene scene = new Scene(pane, 455, 150);
primaryStage.setTitle("Deep Patel"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
////// Your code here that handles events when buttons are clicked
btLear.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
shText.setText(btLear.getText());
taQuote.setText(Quotes("lear.txt"));
}
});
btMacBeth.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
shText.setText(btMacBeth.getText());
}
});
btHamlet.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
shText.setText(btHamlet.getText());
}
});
btRichard.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
shText.setText(btRichard.getText());
}
});
btOthello.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
shText.setText(btOthello.getText());
}
});
}
/////////////////////////////////////////////////////
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
Hi, I am trying to run this code but there is error about exception. I have no idea what to do. Thanks in advance for any help. I tried to put exception in the override method, in the general method and then I just made new method and put exception there but still the same here
The error that I am getting is this:
ShakespeareUI.java:79: error: unreported Exception; must be caught or
declared to be thrown
The EventHandler method does not allow you to add a throws clause for non-runtime exceptions. Therefore you need to use try-catch to handle those exceptions even if you just handle them by rethrowing the exception as RuntimeException (which is not a good way to handle failed execution of code in most cases):
btLear.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent e) {
shText.setText(btLear.getText());
try {
taQuote.setText(Quotes("lear.txt"));
} catch (Exception ex) {
// TODO: handle exception in a differnt way???
throw new RuntimeException(ex);
}
}
});
Note that you should close any classes accessing files as soon as you're done with the reader/writer. (Scanner in this case):
public String Quotes(String fileName) throws Exception{
File file = new File (fileName);
StringBuilder builder = new StringBuilder(); // builder more efficient for concatenating multiple strings
try(Scanner sc = new Scanner(file)) { // try-with-resources automatically calls close on scanner
while(sc.hasNextLine()) {
builder.append(sc.nextLine());
}
return builder.toString();
}
}
This question already has answers here:
Reading a plain text file in Java
(31 answers)
Closed 5 years ago.
I have a program called "AddUser" that allows the user to type in their username and password, which will add this info to user.txt file. I also have a program called "Login" that takes the information the user inputs, username and password, and verifies the input against the user.txt file.
However, I cannot figure out how to validate the input for the Login program. I have found several other posts here, but not from validating from a text file. Any help or guidance would be GREATLY appreciated.
Program Add User
import javax.swing.JOptionPane;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import java.io.*;
public class AddUser extends Application {
private TextField tfUsername = new TextField();
private TextField tfPassword = new TextField();
private Button btAddUser = new Button("Add User");
private Button btClear = new Button("Clear");
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create UI
GridPane gridPane = new GridPane();
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.add(new Label("Username:"), 0, 0);
gridPane.add(tfUsername, 1, 0);
gridPane.add(new Label("Password:"), 0, 1);
gridPane.add(tfPassword, 1, 1);
gridPane.add(btAddUser, 1, 3);
gridPane.add(btClear, 1, 3);
// Set properties for UI
gridPane.setAlignment(Pos.CENTER);
tfUsername.setAlignment(Pos.BOTTOM_RIGHT);
tfPassword.setAlignment(Pos.BOTTOM_RIGHT);
GridPane.setHalignment(btAddUser, HPos.LEFT);
GridPane.setHalignment(btClear, HPos.RIGHT);
// Process events
btAddUser.setOnAction(e -> writeNewUser());
btClear.setOnAction(e -> {
tfUsername.clear();
tfPassword.clear();
});
// Create a scene and place it in the stage
Scene scene = new Scene(gridPane, 300, 150);
primaryStage.setTitle("Add User"); // Set title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public void writeNewUser() {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("users.txt", true))) {
bw.write(tfUsername.getText());
bw.newLine();
bw.write(tfPassword.getText());
bw.newLine();
}
catch (IOException e){
e.printStackTrace();
}
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
Program Login
import javax.swing.JOptionPane;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import java.io.*;
public class Login extends Application {
private TextField tfUsername = new TextField();
private TextField tfPassword = new TextField();
private Button btAddUser = new Button("Login");
private Button btClear = new Button("Clear");
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create UI
GridPane gridPane = new GridPane();
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.add(new Label("Username:"), 0, 0);
gridPane.add(tfUsername, 1, 0);
gridPane.add(new Label("Password:"), 0, 1);
gridPane.add(tfPassword, 1, 1);
gridPane.add(btAddUser, 1, 3);
gridPane.add(btClear, 1, 3);
// Set properties for UI
gridPane.setAlignment(Pos.CENTER);
tfUsername.setAlignment(Pos.BOTTOM_RIGHT);
tfPassword.setAlignment(Pos.BOTTOM_RIGHT);
GridPane.setHalignment(btAddUser, HPos.LEFT);
GridPane.setHalignment(btClear, HPos.RIGHT);
// Process events
btClear.setOnAction(e -> {
tfUsername.clear();
tfPassword.clear();
});
// Create a scene and place it in the stage
Scene scene = new Scene(gridPane, 300, 150);
primaryStage.setTitle("Login"); // Set title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
Consider this Example (Explanation in Comments):
// create boolean variable for final decision
boolean grantAccess = false;
// get the user name and password when user press on login button
// you already know how to use action listener
// (i.e wrap the following code with action listener block of login button)
String userName = tfUsername.getText();
String password = tfPassword.getText();
File f = new File("users.txt");
try {
Scanner read = new Scanner(f);
int noOfLines=0; // count how many lines in the file
while(read.hasNextLine()){
noOfLines++;
}
//loop through every line in the file and check against the user name & password (as I noticed you saved inputs in pairs of lines)
for(int i=0; i<noOfLines; i++){
if(read.nextLine().equals(userName)){ // if the same user name
i++;
if(read.nextLine().equals(password)){ // check password
grantAccess=true; // if also same, change boolean to true
break; // and break the for-loop
}
}
}
if(grantAccess){
// let the user continue
// and do other stuff, for example: move to next window ..etc
}
else{
// return Alert message to notify the deny
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
This program is suppose to store the values in the program to a when write is pressed. Then when read is pressed it will read and display the values. The results are supposed to be displayed in a text area. However, the buttons do not show up when I run the program. When I run it java begins to run on my computer but nothing comes up.
package program;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Date;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class program extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws ClassNotFoundException, IOException {
// Text area
TextArea textArea = new TextArea();
textArea.setStyle("-fx-background-color: lightgrey; -fx-text-fill: blue; -fx-control-inner-background: grey");
textArea.setPadding(new Insets(15, 15, 15, 15));
Button write = new Button("Write");
write.setOnAction(e -> {
// Create an output stream for file
try(ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Exercise17_05.dat", true))) {
int[] numbers = {1, 2, 3, 4, 5};
// Write to file
// 1. Write double
output.writeDouble(5.5);
// 2. Write int array object
output.writeObject(numbers);
// 3. Write date object
output.writeObject(new java.util.Date());
// 4. Write utf string
output.writeUTF("Exercise17_05.dat");
} catch(IOException exception) {
System.exit(0);
}
});
Button read = new Button("Read");
read.setOnAction(e -> {
//Create an input stream for file
try(ObjectInputStream input = new ObjectInputStream(new FileInputStream("Exercise17_05.dat"));){
// Read from file
// 1. Read double
double doubleValue = input.readDouble();
textArea.appendText("Double value: " + doubleValue);
// 2. Read int array object
int[] newNumbers = (int[]) (input.readObject());
textArea.appendText("Integers: " + Arrays.toString(newNumbers));
// 3. Read date object
Date date = (java.util.Date) (input.readObject());
textArea.appendText("DateTime: " + date);
// 4. Read utf string
String fileName = input.readUTF();
textArea.appendText("File name: " + fileName);
} catch(IOException | ClassNotFoundException exception) {
System.exit(0);
}});
HBox hButtons = new HBox(read, write);
VBox vProgram = new VBox(8);
vProgram.getChildren().addAll(hButtons, textArea);
primaryStage.setScene(new Scene(vProgram));
primaryStage.setTitle("Write and Read");
primaryStage.show();
}
}
add these two lines of code at the end of your code, to make your gui visible
primaryStage.setScene(new Scene(vProgram, 300, 250));
primaryStage.show();
I am using JavaFX 8 and specifically the TextArea control. In that control I can enter free form text including "tab" characters. When I enter a tab, the data is spaced in units of 8 characters. For example. In the following, the ! character is where I enter a tab:
1234567890123456789012345678901234567890
! Data here
ABC! Data here
!! Data Here
My puzzle is how to change the tab spacing/sizing for the visual so that instead of the tab size being 8 characters it will only be 4 characters.
To further illustrate, here is an actual screen shot showing tabs in my text area:
I want to leave the data as containing tab characters and not replace tabs with spaces.
This Stack Exchange question does not apply as it talks exclusively about changing tabs to space:
JavaFX TextArea: how to set tabulation width
I decided to grunge through the source code of JavaFX to see if I could find an answer and, although I am not an expert in examining such a large amount of code, I seem to have found that the answer is that the tab size is hard-coded to be 8 characters!!
I found the source file called:
com.sun.javafx.text.PrismTextLayout.java
which has a method called getTabAdvance which returns a fixed value of "8". See the following:
This is most disappointing to me but it is what it is.
After the implementation of JDK-8130738 in JavaFX 14, you can now change the advance of a tab character to any multiple of 'spaceAdvance'. Text and TextFlow now have a tabSize property and the CSS supports -fx-tab-size
Since TextAreaSkin implements the TextArea using Text nodes, you can change the tab size of the TextArea with CSS.
Example:
package example.stackoverflow;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class TextAreaTabs extends Application {
private Scene scene;
private File cssFile;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
var slider = new Slider(1, 50, 8);
slider.valueProperty().addListener((obs, old, newValue) -> {
try {
updateTabSize(newValue.intValue());
} catch (IOException ex) {
System.err.println("Can't write CSS file.");
}
});
var ta = new TextArea("This is a test\n\tafter a tab\n\t1\t2\n");
ta.setFont(Font.font("Monospaced"));
var vbox = new VBox(8,new HBox(8,new Label("Tab size:"),slider),ta);
vbox.setPadding(new Insets(8));
scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.setTitle("TextArea Tab Experiment");
primaryStage.show();
}
private void updateTabSize(int spaces) throws IOException {
File oldFile = cssFile;
cssFile = File.createTempFile("textareatabs", ".css");
cssFile.deleteOnExit();
Files.writeString(cssFile.toPath(), """
Text {
-fx-tab-size: %d;
}
""".formatted(spaces), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
String confStyleSheet = cssFile.toURI().toString();
scene.getStylesheets().setAll(confStyleSheet);
if (oldFile != null) {
oldFile.delete();
}
}
}
Here's a version of Scotts Proggy adapted to use the new JavaFX 17 Data-URI's:
P.S. I use the Azul Zulu openJDK 17 JavaFX Runtime Bundle
You can get that here:
https://www.azul.com/downloads/?package=jdk#download-openjdk
package example.stackoverflow;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.util.Base64;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class TextAreaTabs extends Application {
private static final String CSS_TABSIZE_N = "Text {-fx-tab-size: %d}";
private static final char TAB = '\t';
private static final char NEWLINE = '\n';
private static final String TABBED_TEXT = "This is a test" + NEWLINE + TAB + "after a tab" + NEWLINE + TAB + "1" + TAB + "2";
public static void main(final String[] args) {
launch(args);
}
private Scene scene;
#Override
public void start(final Stage primaryStage) {
final var sliderLabel = new Label("Tab size:");
final var slider = new Slider(1, 50, 8);
; slider.valueProperty().addListener((obs, old, newValue) -> updateTabSize(newValue.intValue()));
final var textArea = new TextArea(TABBED_TEXT);
; textArea.setFont(Font.font("Monospaced"));
final var vBox = new VBox(8, new HBox(8, sliderLabel, slider), textArea);
; vBox.setPadding(new Insets(8));
scene = new Scene(vBox);
primaryStage.setScene(scene);
primaryStage.setTitle("TextArea Tab Experiment");
primaryStage.show();
}
private void updateTabSize(final int tabSize) {
final var styleText = CSS_TABSIZE_N.formatted(tabSize);
final var styleBase64 = Base64.getUrlEncoder().encodeToString(styleText.getBytes(UTF_8));
final var url = "data:text/css;charset=UTF-8;base64," + styleBase64;
System.out.println(styleText + TAB + " -> " + url);
scene.getStylesheets().setAll(url);
}
}