I have been having some issues with a project i am working on. I wish to load my fxml content into an existing anchorpane and display it when the "next" button is clicked, I also wish to have the "back" button to set the anchorpane to the previous fxml file.
The issue I am having is that I have it working only once. If next is clicked it shows the correct fxml content, however if back is pressed it operates correctly once, the second time the window displayed contains no content:
#FXML
AnchorPane scenePane, allContent;
#FXML
public void handleNextAction() {
try {
scenePane.getChildren().clear();
AnchorPane newvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("ProjectDetails.fxml"));
scenePane.getChildren().setAll(newvalscene.getChildren());
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#FXML
public void handleBackAction() {
try {
// allContent.getChildren().clear();
AnchorPane newvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("newProjectWindow.fxml"));
allContent.getChildren().setAll(newvalscene.getChildren());
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
I have tried clearing the content of the anchorpanes however this just results in the anchorpane being empty with no content loaded from the FXML the second time the back button is pressed.
Note I tried debugging this but since there is no actual error its hard to trace and netbeans wont seem to show me the content of variables newvalscene which contains all the nodes to be rendered, but a println shows that it does contain the Vbox and children i expect to be shown.
Any help would be appreciated.
why all these SIr is there a reason ?
scenePane.getChildren().clear();
scenePane.getChildren().setAll(newvalscene.getChildren());//why replace?
allContent.getChildren().setAll(newvalscene.getChildren());//why replace ?
please try this
if you really have this
AnchorPane scenePane, allContent;
and scenePane is your Parent or Root, you can nest your items like
scenePane.getCHildren().add(child);
so relating to your codes
AnchorPane nextvalscene,backvalscene;
public void handleNextAction() {
try {
//scenePane.getChildren().clear(); remove this
if(nextvalscene == null){
nextvalscene = (AnchorPane) FXMLLoader.load(getClass().getResource("ProjectDetails.fxml"));
scenePane.getChildren().add(newvalscene);//change setAll to add and use the child itself
AnchorPane.setLeftNode(newvalscene, 0.0);//set constraint for your newvalscene AnchorPane
//do that for the rest esp top
}
nextvalscene.toFront();
} catch (IOException ex) {
Logger.getLogger(NewProjectController.class.getName()).log(Level.SEVERE, null, ex);
}
}
do same for handleBackAction
Logic is your parent or root scene is AnchorPane it can contain children, so no need to replace all its children, you can have them all inside by obscured by constraints on layout parameters, and change its re-ordering.
unless you have a reason to copying your Anchorpane's children to your scene children list, i think i missed
hope it helps
Related
I have a project I am working on. I am trying to make a dictionary. For that, I have a .csv file with about 55000 words.I am using the trie data structure which has a startsWith() method which checks whether there is a word in the .csv file which matches the given prefix. I had managed to get it to work to find all words that match the given prefix and display them. Now, I have to develop this into a JavaFX app.
So, I thought of using a ComboBox which has its editable attribute set to true so that I could type into it and then the handler associated with the textProperty() of its editor would display all the words starting with given prefix in the listview of the combobox.
Now, the problem I have is that whenever I click the arrow button of the combobox the application stops responding (I think it's because the list view tries to resize itself to fit the items which are 55000).
So, what I want to know is how to disable the arrow button entirely. I have tried to set its background-color to transparent but even then it can still be clicked I want to make it so that it is disabled and transparent basically the combobox ends up looking like a text field.
If there are better, more efficient ways of implementing a dictionary I would appreciate it if you could guide me.
The ListView is a virtual control that only shows a certain number of cells at a time, it doesn't need to "resize itself to the number of items" in any way that would lock up your GUI.
Does this demo program do what you want?
public class Main extends Application {
public static void main(String[] args) throws IOException, URISyntaxException {
launch(args);
}
#Override
public void start(Stage stage) {
List<String> rawWords = Collections.emptyList();
try {
URI wordURI = new URI("https://www-cs-faculty.stanford.edu/~knuth/sgb-words.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(wordURI.toURL().openStream(), StandardCharsets.UTF_8));
rawWords = reader.lines().collect(Collectors.toCollection(() -> new ArrayList<>(6000)));
} catch (IOException | URISyntaxException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
// make the list at least as big as in the question
while(rawWords.size() < 55000) {
ArrayList<String> nextWords = new ArrayList<>(rawWords.size() * 2);
nextWords.addAll(rawWords);
nextWords.addAll(rawWords);
rawWords = nextWords;
}
Collections.sort(rawWords);
ObservableList<String> wordList = FXCollections.observableArrayList(rawWords);
FilteredList<String> filteredList = new FilteredList<>(wordList);
ComboBox<String> combo = new ComboBox<>(filteredList);
combo.setEditable(true);
combo.getEditor().textProperty().addListener((obs, oldVal, newVal) -> {
filteredList.setPredicate(s -> newVal == null || newVal.isEmpty() || s.startsWith(newVal));
});
VBox vbox = new VBox(8,new Label("Dictionary ComboBox"),
combo,
new Label("\n\n\n\nThis space intentionally left blank.\n\n\n\n"));
vbox.setPadding(new Insets(8));
Scene scene = new Scene(vbox, 400, 300);
stage.setTitle("Demo - Filtered Combobox List");
stage.setScene(scene);
stage.show();
}
}
Firstly, sorry for my English. I hope, you unterstand it.
Last Month I started developing a little programm with FXML/ JavaFX.
I have two screens, and I'm switching between them. This is not the problem.
The problem is: On one Screen i have a listview, where i can choose an item. When i have chosen an item, i want to open a new tab on the other screen with the content of the item. Therefore, i have to click on a button.
When i have chosen an item, i can print out the selected item, but how do I open a new tab on the other screen. Both Screens a two different FXML and are activited from the controller. How can I add a Tab, although loading fxml?
public class Controller{
#FXML
private ListView<String> lv;
#FXML
private Button check;
#FXML
public void projectview (Event e3) throws Exception{
Stage stage = null;
Parent root = null;
if(e3.getSource()==check){
//Check is the declaration for the Button on the screen with the listview
String projectview= lv.getSelectionModel().getSelectedItem();
stage = (Stage) check.getScene().getWindow();
root = FXMLLoader.load(getClass().getResource("FXML1.fxml"));
//Here I want to add a tab in FXML1.fxml
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
}
If something is missing or not clear, please ask. I read other similar questions, but i don't know, what to do.
Thanks for help
So here is the problem I am having: I have 3 button, when I press one of the 3 buttons the new scene will display. Yet I cant seem to figure out how to make different panes appear visible depending on which button is pressed. what is the best method to perform this action? How do i use Id's from different scene controllers in order to change the properties of the pane within the main scene button listener?
currently on my main controller when each button is released the below action listener executes and displays secondscreen.fxml. the secondscreen.fxml has 2 different panes, depending on which button is pressed I need 1 of the 2 pains to set to visable.
#FXML
public void handleButtonAction(MouseEvent event) {
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("secondscreen.fxml"));
Stage stage = new Stage();
stage.setTitle("title");
stage.setScene(new Scene(root));
stage.show();
((Node)(event.getSource())).getScene().getWindow();
} catch (Exception e) {
e.printStackTrace();
}
}
After you load a view, you can access its controler.
Keep in mind, that your controller must be asigned to your fxml file fx:controller="your.package.SecondScreenController.java"
FXMLLoader loader = new FXMLLoader.load(getClass().getResource("secondscreen.fxml"));
// load view
Parent root = loader.load();
// after view is loaded, access its controller
SecondScreenController controller = (SecondScreenController) loader.getController();
// modify view using methods on your controller
controller.setTabIndex(0)
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
i have 2 fxml files, LayoutGUI.fxml (main window) and LayoutError.fxml (just a window with 2 textarea's and a ok button). Both have the same controller. I would like to show an occured exception in the LayoutError.fxml. But if i use the setText("") methods of the textareas in the controller i get a NullPointerException. If i set the text in the button clicked action in the controller, there is no exception.
public void showError(String headline,String errorTxt,String stackTrace)
{
Parent root;
try {
root = FXMLLoader.load(getClass().getClassLoader().getResource("application/view/LayoutError.fxml"));
Stage stage = new Stage();
stage.setTitle("Error Message!");
stage.setScene(new Scene(root, 450,300));
stage.show();
error_txtarea_Stacktrace.setText(stackTrace);
error_txtarea_error.setText(errorTxt);
} catch (IOException e) {
e.printStackTrace();
}
}
If i set text here there is no exception. Is it posible that the components not initialized at this time or why can i set the text in the button clicked method and not if i show the window?
#FXML
public void errorButtonOKAction(ActionEvent event)
{
// get a handle to the stage and close it
//Stage stage = (Stage) error_btnOK.getScene().getWindow();
//stage.close();
error_txtarea_Stacktrace.setText("dasds");
error_txtarea_error.setText("dsds");
}
Controller is defined in the error.fxml and the textarea's have Id's.
I have a stage with these properties
stage = new Stage(StageStyle.DECORATED);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.setTitle("My App");
stage.getIcons().add(new Image(icon-address));
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("start.fxml"));
fxmlLoader.setController(this);
...
...//and other properties
It is in full screen in this stage. I have a button and each time I click on it , a method of another class is called and the reference of this stage is passed to it.
For example, if I have two classes Start and ButtonClicked
In Start, I have this :
Button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
buttonClicked a = new buttonClicked ();
try {
a.render(stage);
} catch (Exception ex) {
Logger.getLogger(menuController.class.getName())
.log(Level.SEVERE, null , ex);
}
}
});
Now, the render method is called and I have the following code inside render :
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("buttonclicked.fxml"));
fxmlLoader.setController(this);//set Controller for our fxml file
loader = fxmlLoader.load();//loader is a stackPane because buttonclick.fxml has stackPane
stage.setScene(new Scene(loader));
stage.setFullScreen(true);
...
The problem is, if user clicks on button, stage become a 1024x700(because i have pictures in start.fxml and buttonclicked.fxml. The size of both the picture is 1024x700
After a moment, it becomes full screen. How can i fix this ?
I want to kill the delay in full screen
Thanks
Try
stage.getScene().setRoot(loader);
in render method.
By doing this, the creation of a new scene is eliminated. Therefore I guess, some UI related updates and calculations that must be done after the scene has been shown, are also eliminated.