how to change real time node information in javafx? - java

I'm trying to change the value of a string that is in another method with an event in a button, but when clicking nothing happens.
public class Test extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Objeto1 root = new Objeto1();
Scene scene = new Scene(root.first());
stage.setScene(scene);
stage.show();
}
}
Objeto1
public class Objeto1 {
String tmp ="hola";
public Objeto1() {
}
public VBox first(){
VBox root = new VBox();
setTmp("hola");
HBox button = new HBox();
Button btn = new Button("cliclk");
btn.setOnAction(e->{
setTmp("");
});
button.getChildren().add(btn);
HBox a = form();
root.getChildren().addAll(button,a);
return root;
}
public HBox form(){
HBox root = new HBox();
Label lab = new Label(getTmp());
root.getChildren().add(lab);
return root;
}
public String getTmp() {
return tmp;
}
public void setTmp(String tmp) {
this.tmp = tmp;
}
}
I would like to click on the content of the string change and show in the label the change

Related

How do I call back to the main node so I can switch to a different scene in javafx

so I am trying to switch to a different scene in javafx. I am working on a project where the user will select on a food category via a combobox, which will switch to a new scene that has all the recipes under that specific category.
The problem is I am able to load my MainMenuScene, but I am not sure how to switch to a different scene, which I think is because of how I have structured my code.
My code is structured where I can GUIAPP (which starts the entire GUI)
private static View myView;
private static Recipe myRecipe;
public GUIApp() {
myView = new View();
myRecipe = new Recipe();
}
public static View getView() {
return myView;
}
public static Recipe getRecipe() {
return myRecipe;
}
#Override
public void start(Stage primaryStage) throws Exception {
System.out.println("Starting app...");
myView.setStage(primaryStage);
}
public static void main(String [] args) {
myRecipe = new Recipe();
launch(args);
}
}
Then View, which sets the primary Stage (which is MainMenuScene)
private Stage myStage;
private Scene myMainMenuScene;
private Scene myMealScene;
public View() {
myMainMenuScene = new MainMenuScene(new BorderPane());
}
public Stage getStage() {
return myStage;
}
public Scene getMealScene() {
return myMealScene;
}
public void setStage(Stage primaryStage) {
myStage = primaryStage;
myStage.setScene(myMainMenuScene);
myStage.setTitle("Recipe Database");
myStage.setWidth(600);
myStage.setHeight(400);
Scene scene = myMainMenuScene;
myStage.setScene(scene);
myStage.show();
}
}
Here is MainMenuScene, where it calls the recipe code I had previously made
private BorderPane myRoot;
private String f, t;
Label label = new Label();
public MainMenuScene(Parent root) {
super(root);
myRoot = (BorderPane) root;
BorderPane titleBox = new BorderPane();
titleBox.setStyle("-fx-font: 24 arial;");
myRoot.setTop(titleBox);
Text title = new Text("Recipe Database Tool");
title.setFont(new Font(50));
titleBox.setCenter(title);
//VBox and HBox creation
VBox leftBox = new VBox();
VBox rightBox = new VBox();
VBox centerBox = new VBox();
//Button search = new Button("Recipe Categories");
Button create = new Button("Create/Upload a New Recipe");
//Creates a combobox that gets the category name from Recipe
ComboBox<String> search = new ComboBox<String>();
search.getItems().addAll(GUIApp.getRecipe().getCategory());
search.setOnAction((e) -> {
search.getSelectionModel().selectFirst();
});
/*
****//Create a button that switches to MealScene when a category is selected
Button select = new Button("Select");
select.setOnAction((e) -> {
View.getStage().setScene(View.getMealScene());****
});
*/
//myRoot for each Box
myRoot.setLeft(leftBox);
myRoot.setRight(rightBox);
myRoot.setCenter(centerBox);
//adding the search categories button to the left box
leftBox.setAlignment(Pos.CENTER);
leftBox.setSpacing(30);
leftBox.getChildren().add(search);
//adding the create a new recipe to the right box
rightBox.setAlignment(Pos.CENTER);
rightBox.setSpacing(30);
rightBox.getChildren().add(create);
}
}
I tried calling the button by using View, but I am getting an error that I am not sure how to fix.
Here's the error: It's asking for View.getStage() to make getStage a static method in View, which I don't want to do and View.getMealScene to also become static
Please let me know! I would love to learn how to prevent this in the future

how to switching scenes in javafx (NO FXML)

I ask for your understanding, I am a beginner;)
I'm trying to build a simple application using JavaFX. The problem is that when I open the window the first time it goes well, but if I want to change the scene it throws an error...
Exception in thread "JavaFX Application Thread"
java.lang.IllegalArgumentException:
AnchorPane#1809546[styleClass=root]is already set as root of another
scene#
Main class
public class Main extends Application{
//private Stage primaryStage;
#Override
public void start(Stage primaryStage) {
Login login = new Login();
Scene scene = login.okno();
primaryStage.setTitle("Komunikator sieciowy JAVA");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
//public Stage getPrimaryStage() {
// return this.primaryStage;
//}
public static void main(String[] args) {
launch(args);
}
}
Login
public class Login {
private GridPane grid;
private Scene scene;
private Text title;
private Label nick;
private Button wejdzBtn;
private TextField userName;
//private Alert oknoDlg;
public Login() {
grid = new GridPane();
grid.setAlignment (Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25,25,25,25));
scene = new Scene (grid, 300, 150);
utworzBtn();
utworzLogin();
utworzTekst();
utworzNick();
//oknoDialogowe();
}
//private void oknoDialogowe() {
//Alert oknoDlg = new Alert(Alert.AlertType.CONFIRMATION);
//oknoDlg.setTitle("Informacja");
//oknoDlg.setContentText("test");
// oknoDlg.setHeaderText(null);
//oknoDlg.showAndWait();
//}
private void utworzBtn() {
wejdzBtn = new Button("Zaloguj si\u0119");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment (Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(wejdzBtn);
grid.add(hbBtn, 1, 2);
//wejdzBtn.setDisable(true);
wejdzBtn.setOnAction(e -> {
Messages mess = new Messages();
grid.getScene().setRoot(mess.messa());;
});
}
private void utworzLogin() {
nick = new Label("Nick:");
grid.add(nick, 0, 1);
}
private void utworzNick() {
userName = new TextField();
grid.add(userName,1,1);
// informacja w polu tekstowym
userName.setPromptText("Max 15 znak\u00f3w");
userName.setFocusTraversable(false);
//maksymalna ilość znaków
final int maxLength = 15;
userName.setOnKeyTyped(t -> {
if (userName.getText().length() > maxLength)
{
int pos = userName.getCaretPosition();
userName.setText(userName.getText(0, maxLength));
userName.positionCaret(pos);
}
});
}
private void utworzTekst() {
title = new Text ("Dzień dobry!");
title.setFont(Font.font("Calibri", FontWeight.NORMAL, 20));
grid.add(title, 0, 0, 2, 1);
}
public Scene okno() {
return scene;
}
}
and and a little another class that I'm trying to change with button from login.java
public class Messages {
private AnchorPane anchor;
private Scene scena;
//private Label nick;
private Button sendBtn;
private TextField poleDoWpisywania;
private TextArea poleDoWyswietlania, pobierzNick;
public Messages() {
anchor = new AnchorPane();
scena = new Scene(anchor, 700, 600);
pobierzNick();
poleDoWpisywania();
poleDoWyswietlania();
utworzPrzycisk();
}
private void utworzPrzycisk() {
sendBtn = new Button("Wy\u015Blij");
sendBtn.setDisable(true);
}
private void pobierzNick(){
pobierzNick = new TextArea();
pobierzNick.setEditable(false);
pobierzNick.setWrapText(true);
}
private void poleDoWpisywania() {
poleDoWpisywania = new TextField();
}
private void poleDoWyswietlania() {
poleDoWyswietlania = new TextArea();
poleDoWyswietlania.setEditable(false);
poleDoWyswietlania.setWrapText(true);
}
public Pane messa() {
return anchor;
}
}
could I ask you to show the right way to fix the bug?
JavaFX defines a scene graph which is a tree data structure that has a single root node. For your application (i.e. the code you posted), the root node is the primaryStage (this is the parameter in method start() in class Main). The primaryStage can have several Scenes. Each Scene must have its own root node.
The error message you are getting means that a Scene's root cannot also be the root of another Scene. In other words anchor is the root for scena in class Messages which means it can't be set as the root for scene in class Login.
Apart from that, if you want to change Scene's you need to call method setScene() of class Stage. Here is your Login class and Messages class with changes that solve the run-time error you are getting and perform the scene change when the user clicks on wejdzBtn button.
Login.java
(I only changed the lambda expression in method utworzBtn().)
public class Login {
private GridPane grid;
private Scene scene;
private Text title;
private Label nick;
private Button wejdzBtn;
private TextField userName;
public Login() {
grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25,25,25,25));
scene = new Scene(grid, 300, 150);
utworzBtn();
utworzLogin();
utworzTekst();
utworzNick();
}
private void utworzBtn() {
wejdzBtn = new Button("Zaloguj si\u0119");
HBox hbBtn = new HBox(10);
hbBtn.setAlignment (Pos.BOTTOM_RIGHT);
hbBtn.getChildren().add(wejdzBtn);
grid.add(hbBtn, 1, 2);
wejdzBtn.setOnAction(e -> {
Messages mess = new Messages();
Window w = scene.getWindow();
if (w instanceof Stage) {
Stage s = (Stage) w;
s.setScene(mess.getScena());
}
});
}
private void utworzLogin() {
nick = new Label("Nick:");
grid.add(nick, 0, 1);
}
private void utworzNick() {
userName = new TextField();
grid.add(userName,1,1);
userName.setPromptText("Max 15 znak\u00f3w");
userName.setFocusTraversable(false);
final int maxLength = 15;
userName.setOnKeyTyped(t -> {
if (userName.getText().length() > maxLength)
{
int pos = userName.getCaretPosition();
userName.setText(userName.getText(0, maxLength));
userName.positionCaret(pos);
}
});
}
private void utworzTekst() {
title = new Text ("Dzień dobry!");
title.setFont(Font.font("Calibri", FontWeight.NORMAL, 20));
grid.add(title, 0, 0, 2, 1);
}
public Scene okno() {
return scene;
}
}
Messages.java
(I added method getScena().)
public class Messages {
private AnchorPane anchor;
private Scene scena;
private Button sendBtn;
private TextField poleDoWpisywania;
private TextArea poleDoWyswietlania, pobierzNick;
public Messages() {
anchor = new AnchorPane();
scena = new Scene(anchor, 700, 600);
pobierzNick();
poleDoWpisywania();
poleDoWyswietlania();
utworzPrzycisk();
}
private void utworzPrzycisk() {
sendBtn = new Button("Wy\u015Blij");
sendBtn.setDisable(true);
}
private void pobierzNick() {
pobierzNick = new TextArea();
pobierzNick.setEditable(false);
pobierzNick.setWrapText(true);
}
private void poleDoWpisywania() {
poleDoWpisywania = new TextField();
}
private void poleDoWyswietlania() {
poleDoWyswietlania = new TextArea();
poleDoWyswietlania.setEditable(false);
poleDoWyswietlania.setWrapText(true);
}
public Scene getScena() {
return scena;
}
public Pane messa() {
return anchor;
}
}
Thanks a lot Abra, I've been thinking about it for the last 6 hours and haven't noticed this problem. I have also removed
public Pane messa ();
return anchor;
I do not need it ;)

Access to Javafx elements from another class without FXML

I am using Javafx8 and lets say i have created many ui items (like buttons and so on...). I thought its a good idea to put all EventHandler for these buttons into a separates class. My question is: How can i get access from an EventHandler to any button, e.g. to diable it or to manipulate it on any other way.
Here is a minimum example with two buttons and a separate class for EventHandlers
Let's say this is my Start class:
public class App extends Application
{
#Override
public void start(Stage primaryStage) throws Exception {
Button b1 = new Button();
b1.setOnAction(ListenerClass.createB1Event());
Button b2 = new Button();
b2.setOnAction(ListenerClass.createB2Event());
VBox vbox = new VBox(b1, b2);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main( String[] args )
{
Application.launch(args);
}
}
And my (separate) listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createB1Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Deactivate B1
//Activate B2
}
};
}
public static EventHandler<ActionEvent> createB2Event() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
//Access here to b1 and b2...
//Activate B1
//Dectivate B2
}
};
}
}
Thanks
So based on your principal. You want the button that is located in a vbox and got pressed to be disabled and all other buttons from that vbox to be enabled.
And your problem is how to find button that got pressed.
You need to use ActionEvent.getSource() method.
Heres how I'd code it....
This is Start class:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox vbox = new VBox();
Button b1 = addNewButton("Button1",vbox);
Button b2 = addNewButton("Button2",vbox);
Button b3 = addNewButton("Button3",vbox);
Scene scene = new Scene(vbox, 200, 200);
primaryStage.setTitle("App");
primaryStage.setScene(scene);
primaryStage.show();
}
public static Button addNewButton(String label, VBox ownerVBox){
Button button = new Button(label);
ownerVBox.getChildren().add(button);
button.setOnAction(ListenerClass.createBEvent());
return button;
}
public static void main(String[] args) {
launch(args);
}
}
Listener class:
public class ListenerClass {
public static EventHandler<ActionEvent> createBEvent() {
return new EventHandler<ActionEvent>() {
public void handle(ActionEvent t) {
Button b = (Button) t.getSource();
VBox vbox =(VBox) b.getParent();
vbox.getChildren().forEach(button-> {
button.setDisable(false);
});
b.setDisable(true);
}
};
}
}

JavaFX WebView resize issue

How do I resize a web view correctly? The moment the window gets reduced to a smaller size it seems to push the WebView to the end of the frame, without actually resizing. How would I do this correctly allowing the window to be resized and the WebView to fit in the frame appropriately.
public class OuroborosViewer extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
stage.setTitle("Ouroboros");
Scene scene = new Scene(new VBox(), 1920, 1080);
scene.setFill(Color.OLDLACE);
MenuBar menuBar = new MenuBar();
Menu menuFile = new Menu("File");
Menu menuEdit = new Menu("Edit");
Menu menuView = new Menu("View");
menuBar.getMenus().addAll(menuFile, menuEdit, menuView);
((VBox) scene.getRoot()).getChildren().addAll(menuBar);
BorderPane borderPane = createTab(scene);
((VBox) scene.getRoot()).getChildren().add(borderPane);
scene.widthProperty().addListener(new WidthListener());
scene.heightProperty().addListener(new HeightListener());
// stage.getIcons().add(new Image("Ouroboros.svg"));
stage.setScene(scene);
try {
sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(OuroborosViewer.class.getName()).log(Level.SEVERE, null, ex);
}
stage.show();
}
private BorderPane createTab(Scene scene) {
TabPane tabPane = new TabPane();
BorderPane borderPane = new BorderPane();
Tab tab = new Tab();
tab.setText("Google");
//VBox hbox = new VBox(new BrowserToolbar(scene), new OuroborosBrowser(scene));
VBox vbox = new VBox();
BrowserToolbar toolbar = new BrowserToolbar(scene);
OuroborosBrowser ob = new OuroborosBrowser(scene);
VBox.setVgrow(toolbar, Priority.ALWAYS);
VBox.setVgrow(ob, Priority.ALWAYS);
vbox.getChildren().addAll(toolbar, ob);
vbox.autosize();
tabPane.getTabs().add(tab);
tab.setContent(vbox);
borderPane.setTop(tabPane);
return borderPane;
}
private static class WidthListener implements ChangeListener<Number> {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneWidth, Number newSceneWidth) {
OuroborosBrowser.browsers[0].setPrefWidth(newSceneWidth.doubleValue());
BrowserToolbar.URLBars[0].setPrefWidth(newSceneWidth.doubleValue() - 115);
BrowserToolbar.toolBars[0].setPrefWidth(newSceneWidth.doubleValue());
}
}
private static class HeightListener implements ChangeListener<Number> {
#Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneHeight, Number newSceneHeight) {
if (oldSceneHeight != newSceneHeight) {
try {
OuroborosBrowser.browsers[0].setPrefHeight(newSceneHeight.doubleValue()
+ OuroborosBrowser.browsers[0].getScene().getRoot().getChildrenUnmodifiable()
.get(0).prefHeight(0));
} catch (Exception ex) {
}
}
}
}
}
class OuroborosBrowser extends Region {
public static int browserCounter = 0;
public static WebView[] browsers = new WebView[25];
private static WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
public OuroborosBrowser(Scene scene) {
browser.setPrefSize(scene.getWidth(), scene.getHeight());
webEngine.load("http://www.google.com/index.html");
getChildren().add(browser);
browsers[browserCounter] = browser;
browserCounter++;
}
}
public class BrowserToolbar extends Region {
public static TextField[] URLBars = new TextField[25];
public static ToolBar[] toolBars = new ToolBar[25];
public static int barCounter = 0;
public BrowserToolbar(Scene scene) {
Button backButton = new Button(" < ");
Button forwardButton = new Button(" > ");
TextField URLbar = new TextField();
URLbar.setPrefWidth(scene.getWidth() - 115);
URLBars[barCounter] = URLbar;
URLbar.setPrefWidth(2000);
final ToolBar toolbar = new ToolBar(
backButton, forwardButton, URLbar);
toolbar.setPrefWidth(2000);
toolBars[barCounter] = toolbar;
barCounter++;
HBox hb = new HBox();
hb.getChildren().add(toolbar);
hb.setPrefWidth(scene.getWidth());
hb.autosize();
getChildren().add(hb);
}
}
The area shaded in the image below is the area that keeps increasing as the frame height is reduced.
link to image

Web Browser Link manipulation

public class WebWiewYahoo extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
VBox root = new VBox();
Button go = new Button("go");
final TextField address = new TextField("http://www.yahoo.com");
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
HBox toolBar1 = new HBox();
toolBar1.setAlignment(Pos.TOP_LEFT);
toolBar1.getChildren().addAll(address, go);
// load the web page
webEngine.load("http://www.yahoo.com");
root.getChildren().add(toolBar1);
root.getChildren().add(browser);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
//I want to manipulate link in browser.So that even on clicking any link at any point i could redirect it to yahoo.com.Please help.
You could try to do this :
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
#Override
public void changed(ObservableValue<? extends State> paramObservableValue,
State oldState,
State newState) {
if (State.SCHEDULED == newState && !"http://www.yahoo.com/".equals(webEngine.getLocation())) {
webEngine.load("http://www.yahoo.com");
}
}
});

Categories