Editing nodes in the run JavaFX - javafx

I'm trying to add nodes from separate fxml file to scroll pane but I'm failing to edit each node
in the run, the result is the same look of every node in scroll pane.
Here is the code :
private void refreshNodes()
{
pnl_scroll.getChildren().clear();
Node [] nodes = new Node[15];
for(int i = 0; i<10; i++)
{
try {
nodes[i] = (Node)FXMLLoader.load(getClass().getResource("/fxml/Item.fxml"));
//I need to edit each node, to set data on certain labels by their fx:id, I tried but failed
pnl_scroll.getChildren().add(nodes[i]);
} catch (IOException ex) {
Logger.getLogger(HomeController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Here is the look of the node(Item.fxml) :
How can I access for example "Quote in progress" label from the node so that I can set different text on it in the run?

Related

How to disable the arrow button in JavaFX combo box

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();
}
}

reading and writing file in javafx program

I'm writing a program writes and read the file. it has 50 numbers and if users enter number more than 50 it should ask the users to enter it again. my question is for the error it should show the message box but again return to the text field for input. Also one more question, for example, user1 is entering 1 and user2 is also entering 1, it should tell the user2 "please enter another number it's already entered." how can I do it in writing and reading files.
this is my code:
public class JavaFXApplication24 extends Application {
private int seatInput;
#Override
public void start(Stage primaryStage) {
StackPane pane = new StackPane();
HBox hbox = new HBox();
Label num = new Label("Please enter the number from 1 to 50: ");
TextField numInput = new TextField();
File file = new File("NumberBook.txt");
Button ok = new Button("ok");
ok.setOnAction((new EventHandler<ActionEvent>(){
public void handle(final ActionEvent event ){
try{
if ((numInput.getText().equals(1)&& numInput.getText().equals(50))){
}else{
String input = JOptionPane.showInputDialog("Please enter again");
}
}
catch (HeadlessException | NumberFormatException e) {
}
try {
PrintWriter output = new PrintWriter(file);
} catch (IOException ex) {
System.out.printf("error", ex);
}
try {
Scanner input1 = new Scanner(file);
System.out.printf("Entered: %s", seatInput);
} catch (FileNotFoundException ex) {
System.out.printf("error", ex);
}
}
}));
hbox.getChildren().addAll(num,numInput,ok);
pane.getChildren().addAll(hbox);
Scene secondScene = new Scene(pane, 600, 400);
// New window (Stage)
Stage newWindow = new Stage();
newWindow.setTitle("Booking and Timing");
newWindow.setScene(secondScene);
newWindow.show();
}
}
From a quick glance here are some problems with your code:
1) if ((numInput.getText().equals(1)&& numInput.getText().equals(50))). There are 2 problems here. Firstly, as fabian pointed out, this statement will always evaluate to false. Secondly, from your question I think you want the user to enter a number from 1 to 50, but here you're checking if they enter 1 and 50 (which also means it's always false).
2) JOptionPane.showInputDialog("Please enter again") Because your application is JavaFX, you should use the built in Dialog instead.
Now to answer your questions, you can call requestFocus on the text field right after the error message is displayed. Your second question seems like you want some networking functionality in the application, which adds a whole lot of complexity to it. You might need to do some research on how to do it in Java.

Add level in JavaFX during loading operation

I have the following UI
So , you insert a keyword and then press "Cerca" (it's like Search in Italian) , then the Google Custom Search Api show the first 10 pictures. During the Custom search API are processing the results (the pictures) I want to show an other picture like this
(I know it's big but the dimension is not the main point now). My idea is simple, I want to put the picture one "level"(don't know exactly how to call ) over the UI, then the picture will be not visible in 3 case: 1) When the API will end their job 2)If I don't have results 3) If I get an exception. My question is, which is the best approach to do this ? And then, Should I use Threads?
I hope I was clear
UPDATE:
This is the code of "cerca" button
cerca.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// Task<Boolean> task = new Task <Boolean>(){
//
// #Override
// protected Boolean call() throws Exception {
// // TODO Auto-generated method stub
// return null;
// }
//
//
// };
String searchKeyWord = userTextField.getText();
result = getSearchResult(searchKeyWord);
for ( i=0; i<result.size(); i++)
{
System.out.println("" +result.get(i));
ImageView resultview;
resultview = new ImageView(result.get(i));
resultview.setFitWidth(130);
resultview.setFitHeight(130);
// resultview.setStyle("-fx-border:6; -fx-border-color: green;");
if(j==4)
{
j=0;
k++;
}
resultgrid.add(resultview, j,k );
j++;
VBox vbox = new VBox();
resultgrid.setHgap(50);
resultgrid.setVgap(50);
// resultgrid.setStyle("-fx-border:1; -fx-border-color: red;");
vbox.getChildren().add(resultgrid);
vbox.setSpacing(10);
vbox.setPadding(new Insets(90, 0, 10, 220)); //TOP RIGHT BOTTOM LEFT
// content.setAlignment(resultgrid, Pos.TOP_RIGHT);
getChildren().add(vbox);
final int ind = i;
resultview.setOnMouseClicked((ev) ->{
if (ev.getClickCount()==2)
{
image = SwingFXUtils.fromFXImage(resultview.getImage(), null);
parent.setCrop(image);
}
});
}
}
});
Have a look at Task. It has setOnSucceeded() and setOnFailed() which will come handy in your case.
You can basically create a new Task when the search takes place. The search will run in background and you can show the loading UI in the screen.
If the task completes successfully, you can load the new screen with the results.
If the task fails, you can show an error message near the search TextField.
In case of exception, you can catch it and write the necessary code.

JavaFX : How to make a mark where between two imageview in tilepane

I try to make a slide frame looks like powerpoint using imageview and tilepane.
Let's suppose we are in powerpoint. In photo, there are blue background panel(tilepane) and slide(imageview).
I want make a mark(line) that is red arrow pointed in photo, when I locate mouse cursor where between slide5 and slide6. Can I make?
And how to get the each hgap area's information?
ex) Which hgap clicked?
I can get the each slide(imageview) value, but I can't find how to get the hgap's information.
This is my partial code.
String[] imageName = {"slide1.png", "slide2.png", "slide3.png", "slide4.png",
"slide5.png", "slide6.png", "slide7.png", "slide8.png"};
Image img = null;
for (int i = 0; i < imageName.length; i++) {
try {
img = new Image(getClass().getResourceAsStream(imageName[i]));
} catch (Exception e) {
System.out.println("exception : " + e);
}
ImageView imageview = new ImageView(img);
imageview.setUserData(imageName[i]);
imageview.setFitWidth(widthImageView);
imageview.setFitHeight(heightImageView);
HBox hbox= new HBox();
hbox.getChildren().add(imageview);
tile1.getChildren().add(hbox); }
The hgap and vgap parameters are used for calculating the space between the nodes. You can't put a node in there. You should evaluate your requirements and consider using a different layout like e. g. GridPane.

Show Image Dynamically in ScrollPane JavaFx

I want to add Multiple images in Scollpane by clicking button i try below code but it will not display image any idea about that?
#FXML private void OnClick(ActionEvent ae)
{
getGalleryView();
}
public void getGalleryView()
{
ScrolPane sp=new ScroPane();
Hbox hb=new Hbox();
Image [] images=new Image[5];
ImageView []pics=new ImageView[5];
final String [] imageNames = new String [] {"fw1.jpg", "fw2.jpg",
"fw3.jpg", "fw4.jpg", "fw5.jpg"};
for (int i = 0; i < 5; i++) {
images[i] = new Image(getClass().getResourceAsStream(imageNames[i]));
pics[i] = new ImageView(images[i]);
pics[i].setFitWidth(100);
pics[i].setPreserveRatio(true);
hb.getChildren().add(pics[i]);
sp.setContent(hb);
}
}
You need to add the scrollpane to the scene:
#FXML private void OnClick(ActionEvent ae)
{
getGalleryView(ae);
}
public void getGalleryView(ActionEvent ae)
{
ScrolPane sp=new ScroPane();
Hbox hb=new Hbox();
Image [] images=new Image[5];
ImageView []pics=new ImageView[5];
final String [] imageNames = new String [] {"fw1.jpg", "fw2.jpg",
"fw3.jpg", "fw4.jpg", "fw5.jpg"};
for (int i = 0; i < 5; i++) {
images[i] = new Image(getClass().getResourceAsStream(imageNames[i]));
pics[i] = new ImageView(images[i]);
pics[i].setFitWidth(100);
pics[i].setPreserveRatio(true);
hb.getChildren().add(pics[i]);
sp.setContent(hb);
}
Scene scene = ((Node) ae.getSource()).getScene();
((Pane) scene.getRoot()).getChildren().add(sp);
}
I assumed here that your root node is a Pane or one of its subclasses.
ScrolPane sp=new ScroPane(); error?
EDIT:
I was developing similar method. Mine works fine. You can check if you want to.
private List<String> listFileNames(File folder) throws NullPointerException{
List<String> list = new ArrayList<>();
for (File file : folder.listFiles()) {
if (file.isDirectory())
listFileNames(file);
else {
System.out.println(file.getName());
list.add(file.getName());
}
}
return list;
}
private void insertImages(List<String> list, Hero thisHero) {
int column = 0;
int row = 0;
for (String path:list) {
String fullPath = "file:"+thisHero.getHeroClass().getFile()+"\\"+path;
ToggleButton button = new ToggleButton();
button.setBackground(Background.EMPTY);
button.setGraphic(new ImageView(new Image(fullPath)));
grid.add(button,column,row);
column++;
if (column == 5) {
row++;
column = 0;
}
}
}
I can write more if you want. I use Lists because of it's ease of adding items.
You can use first method to just get all file names to list, from your folder filled with image files.
Second method does the job of making new ImageViews filled with ToggleButtons with graphic. I just changed the concept to buttons, so sorry about my laziness of not changing code to exactly fit your needs.
Path is the exact file name, thisHero.getHeroClass().getFile() returns path to the directory which contains this image.
grid.add(button, column, row) adds this button to the grid pane which i made before. It's my app, so sorry for not sharing all the code, but i thought that this snippet could be usefull.
EDIT2: You could also provide us with error information if there is any.

Resources