how to keep space between images in scrollpane - button

I need to space up between images in a scrollpane.I'm adding an imageview and a button to a Vbox.Then that vbox to a gridpane.gridpane is added to scrollpane.However,scrollpane gets overcrowded.I've used gridpane.setPadding(), but no effect.
here's my code:
File file = new File("D:\\SERVER\\Server Content\\Apps\\icons");
File[] filelist1 = file.listFiles();
ArrayList<File> filelist2 = new ArrayList<>();
for (File file1 : filelist1) {
filelist2.add(file1);
}
btnar=new ArrayList<>();
for (int i = 0; i < filelist2.size(); i++) {
downloadbtn=new Button("Download");
btnar.add(downloadbtn);
}
System.out.println(filelist2.size());
gridpane.setAlignment(Pos.CENTER);
gridpane.setPadding(new Insets(50, 50, 50, 50));
gridpane.setHgap(50);
gridpane.setVgap(50);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setFillWidth(true);
columnConstraints.setHgrow(Priority.ALWAYS);
gridpane.getColumnConstraints().add(columnConstraints);
int imageCol = 0;
int imageRow = 0;
for (int i = 0; i < filelist2.size(); i++) {
System.out.println(filelist2.get(i).getName());
image = new Image(filelist2.get(i).toURI().toString());
pic = new ImageView();
pic.setFitWidth(130);
pic.setFitHeight(130);
pic.setImage(image);
vb = new VBox();
vb.getChildren().addAll(pic,btnar.get(i));
gridpane.add(vb, imageCol, imageRow);
GridPane.setMargin(pic, new Insets(2,2,2,2));
imageCol++;
// To check if all the 3 images of a row are completed
if (imageCol > 2) {
// Reset Column
imageCol = 0;
// Next Row
imageRow++;
}
}
here' how my stage looks like when images are added

Your code looks fine to me. I have tried your code with a folder filled with images. I wrapped the GridPane on a ScrollPane and gave the ScrollPane a defined size. The space between ImageViews are as per the HGap and VGap provided. Here is a image to second my findings.
Note
If you are looking for gaps between ImageView in a GridPane use setHgap() and setVgap()
setPadding() is used to set the margin around the grid. You can ofcourse use a mix of both as I have done below
Please find this MCVE to support you find your mistake
import java.io.File;
import java.util.ArrayList;
import java.util.List;
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.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class LoadingImages extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
ScrollPane scrollPane = new ScrollPane();
GridPane gridpane = new GridPane();
scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
scrollPane.setPrefSize(500, 500);
scrollPane.setContent(gridpane);
Scene scene = new Scene(scrollPane);
primaryStage.setScene(scene);
primaryStage.show();
File file = new File("Path to folder with images");
File[] filelist1 = file.listFiles();
ArrayList<File> filelist2 = new ArrayList<>();
for (File file1 : filelist1) {
filelist2.add(file1);
}
List btnar=new ArrayList<>();
for (int i = 0; i < filelist2.size(); i++) {
Button downloadbtn=new Button("Download");
btnar.add(downloadbtn);
}
System.out.println(filelist2.size());
gridpane.setAlignment(Pos.CENTER);
gridpane.setPadding(new Insets(50, 50, 50, 50));
gridpane.setHgap(50);
gridpane.setVgap(50);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setFillWidth(true);
columnConstraints.setHgrow(Priority.ALWAYS);
gridpane.getColumnConstraints().add(columnConstraints);
int imageCol = 0;
int imageRow = 0;
for (int i = 0; i < filelist2.size(); i++) {
System.out.println(filelist2.get(i).getName());
Image image = new Image(filelist2.get(i).toURI().toString());
ImageView pic = new ImageView();
pic.setFitWidth(130);
pic.setFitHeight(130);
pic.setImage(image);
VBox vb = new VBox();
vb.getChildren().addAll(pic,(Button)btnar.get(i));
gridpane.add(vb, imageCol, imageRow);
GridPane.setMargin(pic, new Insets(2,2,2,2));
imageCol++;
// To check if all the 3 images of a row are completed
if (imageCol > 2) {
// Reset Column
imageCol = 0;
// Next Row
imageRow++;
}
}
}
public static void main(String[] args) {
launch(args);
}
}

Related

Removing node at particular column of GridPane with mousepress

I am trying to remove multiple nodes, one at a time, from a GridPane by first getting the coordinates on mousepress, then using gridpane.getChildren().remove(column) using column as the index to remove. This works as expected if I start with an arbitrary index and then mousepress on a lesser valued index, however it does not work if I try to mousepress on a greater valued index, the mousepress value retains the previous value of the node.
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DominoMain extends Application {
GridPane humanHand = new GridPane();
ImageView imageView;
int column;
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = new AnchorPane();
List<ImageView> tiles = new ArrayList<>();
String[] imageResources = new String[] {
"00.jpg", "10.jpg", "11.jpg", "20.jpg", "21.jpg", "22.jpg",
"30.jpg", "31.jpg", "32.jpg", "33.jpg", "40.jpg", "41.jpg",
"42.jpg", "43.jpg", "44.jpg", "50.jpg", "51.jpg", "52.jpg",
"53.jpg", "54.jpg", "55.jpg", "60.jpg", "61.jpg", "62.jpg",
"63.jpg", "64.jpg", "65.jpg", "66.jpg"};
for(final String imageResource : imageResources) {
imageView = new ImageView(imageResource);
imageView.setFitWidth(50);
imageView.setFitHeight(26);
tiles.add(imageView);
}
//Assign mouse press handler.
for (ImageView imageView :
tiles) {
imageView.setOnMousePressed(this::onPress);
}
Collections.shuffle(tiles);
for (int i = 0; i < 7; i++) {
GridPane.setHalignment(tiles.get(0), HPos.CENTER);
humanHand.add(tiles.remove(0), i, 0);
}
humanHand.setOnMousePressed(event -> {
System.out.printf("Index to be removed %d \n", column);
humanHand.getChildren().remove(column);
});
humanHand.setAlignment(Pos.BOTTOM_CENTER);
AnchorPane.setBottomAnchor(humanHand, 25.0);
AnchorPane.setLeftAnchor(humanHand, 0.0);
AnchorPane.setRightAnchor(humanHand, 0.0);
root.getChildren().addAll(humanHand);
primaryStage.setScene(new Scene(root, 800, 350));
primaryStage.show();
}
//Handler for mouse press event.
private void onPress(MouseEvent event) {
column = GridPane.getColumnIndex((Node) event.getSource());
int row = GridPane.getRowIndex((Node) event.getSource());
System.out.printf("Node clicked at: column=%d, row=%d \n", column, row);
System.out.println(humanHand.getChildren().get(column));
}
}
Any help would be appreciated.
Just keep track of which ImageView is clicked on, instead of which column:
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class DominoMain extends Application {
GridPane humanHand = new GridPane();
private ImageView clickedImage ;
#Override
public void start(Stage primaryStage) throws Exception {
AnchorPane root = new AnchorPane();
List<ImageView> tiles = new ArrayList<>();
String[] imageResources = new String[] {
"00.jpg", "10.jpg", "11.jpg", "20.jpg", "21.jpg", "22.jpg",
"30.jpg", "31.jpg", "32.jpg", "33.jpg", "40.jpg", "41.jpg",
"42.jpg", "43.jpg", "44.jpg", "50.jpg", "51.jpg", "52.jpg",
"53.jpg", "54.jpg", "55.jpg", "60.jpg", "61.jpg", "62.jpg",
"63.jpg", "64.jpg", "65.jpg", "66.jpg"};
for(final String imageResource : imageResources) {
ImageView imageView = new ImageView(imageResource);
imageView.setFitWidth(50);
imageView.setFitHeight(26);
tiles.add(imageView);
}
//Assign mouse press handler.
for (ImageView imageView :
tiles) {
imageView.setOnMousePressed(e -> clickedImage = imageView);
}
Collections.shuffle(tiles);
for (int i = 0; i < 7; i++) {
GridPane.setHalignment(tiles.get(0), HPos.CENTER);
humanHand.add(tiles.remove(0), i, 0);
}
humanHand.setOnMousePressed(event -> {
if (clickedImage != null) {
humanHand.getChildren().remove(clickedImage);
}
});
humanHand.setAlignment(Pos.BOTTOM_CENTER);
AnchorPane.setBottomAnchor(humanHand, 25.0);
AnchorPane.setLeftAnchor(humanHand, 0.0);
AnchorPane.setRightAnchor(humanHand, 0.0);
root.getChildren().addAll(humanHand);
primaryStage.setScene(new Scene(root, 800, 350));
primaryStage.show();
}
}

How to change color of text in JavaFX Label

I am having trouble changing colors of text that are within the JavaFX label class.
This is the code I have so far.
package Problem2;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Problem2Code extends Application {
Slider[] slider = new Slider[4];
#Override
public void start(Stage primaryStage) throws Exception {
Text text = new Text("Show Colors");
// Bottom pane
Label[] labels = new Label[4];
String[] stringLabels = {"Red", "Green", "Blue", "Opacity"};
GridPane gridPane = new GridPane();
gridPane.setHgap(30);
gridPane.setVgap(5);
gridPane.setPadding(new Insets(25));
gridPane.setAlignment(Pos.CENTER);
for (int i = 0; i < slider.length; i++) {
slider[i] = new Slider();
slider[i].setMin(0);
if (!stringLabels[i].equals("Opacity")) {
slider[i].setMax(255);
slider[i].setValue(255);
} else {
slider[i].setMax(1);
slider[i].setValue(1);
}
labels[i] = new Label(stringLabels[i]);
slider[i].valueProperty()
.addListener((obser, old, newV) -> text.setFill(getColor()));
gridPane.add(labels[i], 0, i);
gridPane.add(slider[i], 1, i);
}
StackPane stackPane = new StackPane(text);
stackPane.setPrefSize(315, 65);
BorderPane borderPane = new BorderPane(stackPane);
borderPane.setBottom(gridPane);
primaryStage.setScene(new Scene(borderPane));
primaryStage.setTitle("Color Changer");
primaryStage.show();
}
private Color getColor() {
// r g b o
double[] rgb = new double[4];
for (int i = 0; i < rgb.length; i++) {
rgb[i] = slider[i].getValue();
}
return Color.rgb((int)rgb[0], (int)rgb[1], (int)rgb[2], rgb[3]);
}
public static void main(String[] args) {
Application.launch(args);
}}
When I build it and play with the sliders, this is what it looks like.
How can I edit the colors of text "Red", "Green", and "Blue", so the text colors matches the words like this?
I believe it has to do something with making an HBox? I tried it with that but didn't know how to do it correctly. I also tried making variables stringLabels1, stringLabels2, stringLabels3, and stringLabels4 for each of the strings, but had trouble with that in the gridPane portion. Having trouble coding either of those.
Please help, thank you.
Use setTextFill on label, below will set text color to Red:
labels[i].setTextFill(Color.color(1, 0, 0));
You could use Color#web method:
for (int i = 0; i < slider.length; i++) {
slider[i] = new Slider();
slider[i].setMin(0);
labels[i] = new Label(stringLabels[i]);
if (!stringLabels[i].equals("Opacity")) {
slider[i].setMax(255);
slider[i].setValue(255);
labels[i].setTextFill(Color.web(stringLabels[i])); //css alternative: labels[i].setStyle("-fx-text-fill: " + stringLabels[i]);
} else {
slider[i].setMax(1);
slider[i].setValue(1);
}
slider[i].valueProperty()
.addListener((obser, old, newV) -> text.setFill(getColor()));
gridPane.add(labels[i], 0, i);
gridPane.add(slider[i], 1, i);
}
Side note: you could use one listener for all four sliders:
ChangeListener<Number> listener = (obser, old, newV) -> text.setFill(getColor());
for (int i = 0; i < slider.length; i++) {
..
slider[i].valueProperty().addListener(listener);
..
}

Detecting button click of button added to javafx listview

I am very new to Java so please be patient with me. I have successfully added buttons, labels and even a progress bar to a listview cell. I need to be able to detect when one of the buttons has been clicked. Adding controls to listview content I managed to get from a couple of posts here the code i am using is shown below
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class ListViewDemo extends Application {
public static class lvCell extends VBox {
Label labelName = new Label();
Label labelPath = new Label();
Label labelElapse = new Label();
Button buttonPlayPause = new Button();
Button buttonStop = new Button();
ImageView ivStop = new ImageView();
ImageView ivPlay = new ImageView();
Pane buttonSpacer = new Pane();
Pane progressBarSpacer = new Pane();
HBox hbDetail = new HBox();
HBox hbProgress = new HBox();
ProgressBar pbProgress = new ProgressBar();
File filePlay;
File fileStop;
double prefWidth = 10;
double prefHeight = 10;
lvCell(String labelText) {
super();
labelName.setText(labelText);
labelName.setMaxWidth(Double.MAX_VALUE);
labelPath.setMaxWidth(0);
labelPath.setText("Path");
pbProgress.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(labelName, Priority.ALWAYS);
HBox.setHgrow(pbProgress, Priority.ALWAYS);
HBox.setMargin(labelName, new Insets(5, 0, 0, 0));
HBox.setMargin(pbProgress, new Insets(0, 0, 0, 0));
labelPath.setVisible(false);
buttonSpacer.setPrefSize(prefWidth, prefHeight);
labelElapse.setPrefSize(50, prefHeight);
labelElapse.setText("Time");;
progressBarSpacer.setPrefSize(prefWidth * 6, prefHeight);
filePlay = new File("src/image/play.png");
fileStop = new File("src/image/stop.png");
Image imagePlay = new Image(filePlay.toURI().toString());
Image imageStop = new Image(fileStop.toURI().toString());
ivPlay.setImage(imagePlay);
ivStop.setImage(imageStop);
ivPlay.setFitHeight(prefHeight);
ivPlay.setFitWidth(prefWidth);
ivStop.setFitHeight(prefHeight);
ivStop.setFitWidth(prefWidth);
buttonPlayPause.setGraphic(ivPlay);
buttonStop.setGraphic(ivStop);
buttonPlayPause.setMaxSize(prefWidth, prefHeight);
buttonStop.setMaxSize(prefWidth, prefHeight);
pbProgress.setMaxHeight(2);
pbProgress.setPrefHeight(2);
hbDetail.getChildren().addAll(buttonPlayPause, buttonStop, buttonSpacer, labelName, labelPath);
hbProgress.getChildren().addAll(progressBarSpacer, pbProgress, labelElapse);
this.getChildren().addAll(hbDetail, hbProgress);
}
}
public Parent createContent() {
BorderPane layout = new BorderPane();
List < lvCell > list = new ArrayList < > ();
for (int i = 0; i < 10; i++) {
list.add(new lvCell("Item " + i));
}
ListView < lvCell > listView = new ListView < lvCell > ();
ObservableList < lvCell > myObservableList = FXCollections.observableList(list);
listView.setItems(myObservableList);
layout.setCenter(listView);
return layout;
}
#Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setWidth(300);
stage.setHeight(200);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
}
The screen looks like this:
Any help will be greatly appreciated.
Thanks in advance, and wishing you a peaceful journey.
Yas
This is not a class well designed to put into a ListView. An object used as item in a ListView should contain data; the ListCell implementation produced by the cellFactory is responsible for determining the visual representation of the data in the ListView. This way you avoid the creation of nodes for every object reducing the memory footprint, which is exactly what ListView is designed for.
Simplified example
The data here contains just the progress and some text; it's displayed in a ProgressBar and the text of the cell; an additional button in the cell allows increasing the progress by 0.25 for each click and removing any items reaching a progress of 1.
Data class
public class Data {
private final DoubleProperty progress = new SimpleDoubleProperty();
private final String text;
public Data(String text) {
this.text = text;
}
public double getProgress() {
return progress.get();
}
public void setProgress(double value) {
progress.set(value);
}
public String getText() {
return text;
}
public ObservableValue<? extends Number> progressProperty() {
return progress;
}
}
ListView code
ListView<Data> listView = new ListView<>(someData);
listView.setCellFactory(l -> new ListCell<Data>() {
private final ProgressBar progressBar = new ProgressBar();
private final Button button = new Button("increase");
private final HBox content = new HBox(progressBar, button);
{
button.setOnAction(evt -> {
Data item = getItem();
int index = getIndex();
double progress = item.getProgress() + 0.25;
item.setProgress(progress);
if (progress >= 1) {
getListView().getItems().remove(index);
}
});
}
#Override
protected void updateItem(Data item, boolean empty) {
super.updateItem(item, empty);
progressBar.progressProperty().unbind();
if (item == null) {
setGraphic(null);
setText("");
} else {
setGraphic(content);
setText(item.getText());
progressBar.progressProperty().bind(item.progressProperty());
}
}
});

Select entire column/s with checkbox and display it in a new table

I'm creating a JavaFX application which enables user to select columns from a ResultSet and display the selected columns to a new table.
I want to select the columns through a check box and it would be better if the whole selected column will be highlighted.
I can do this in Java easily because Java has getSelectedColumns() method but I have no idea on how to do it in JavaFX since I started trying this only few days ago.
in Java, it goes like this:
int[] colIndices2 = table.getSelectedColumns();
int colCount = table.getSelectedColumnCount();
int rowCount = table.getRowCount();
for(int i=0; i<colIndices2.length; i++){
colNames.addElement(table.getColumnName(colIndices2[i]));
}
for(int i=0; i<rowCount; i++){
Vector<Object> row = new Vector<>(colCount);
for (int j=0; j<colIndices2.length; j++){
row.addElement(table.getValueAt(i,colIndices2[j]));
}
colData.addElement(row);
}
DefaultTableModel model = new DefaultTableModel(colData, colNames);
table2.setModel(model);
//table - populated with data from database
//table2 - table containing the selected columns from table1
I want to convert these codes into JavaFX but I'm having a hard time.
This should get you started...
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SelectTest extends Application
{
#Override
public void start(Stage primaryStage)
{
TableView<LineItem> table = new TableView<>();
table.setItems(FXCollections.observableArrayList(new LineItem()));
TableColumn<LineItem, String> column1 = new TableColumn<>("Test1");
column1.setCellValueFactory(cellData -> cellData.getValue().string1Property());
column1.setEditable(true);
CheckBox selectCol1 = new CheckBox();
column1.setGraphic(selectCol1);
column1.setSortable(false);
selectCol1.setOnAction((ActionEvent e) ->
{
selectColumn(column1, selectCol1.isSelected());
table.refresh();
});
table.getColumns().add(column1);
TableColumn<LineItem, String> column2 = new TableColumn<>("Test2");
column2.setCellValueFactory(cellData -> cellData.getValue().string2Property());
column2.setEditable(true);
CheckBox selectCol2 = new CheckBox();
column2.setGraphic(selectCol2);
column2.setSortable(false);
selectCol2.setOnAction((ActionEvent e) ->
{
selectColumn(column2, selectCol2.isSelected());
table.refresh();
});
table.getColumns().add(column2);
TableColumn<LineItem, String> column3 = new TableColumn<>("Test3");
column3.setCellValueFactory(cellData -> cellData.getValue().string3Property());
column3.setEditable(true);
CheckBox selectCol3 = new CheckBox();
column3.setGraphic(selectCol3);
column3.setSortable(false);
selectCol3.setOnAction((ActionEvent e) ->
{
selectColumn(column3, selectCol3.isSelected());
table.refresh();
});
table.getColumns().add(column3);
StackPane root = new StackPane();
root.getChildren().add(table);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
private static void selectColumn(TableColumn column, boolean select)
{
if (select)
{
column.setStyle("-fx-background-color: rgba(3, 169, 244, 0.5)");
} else
{
column.setStyle(null);
}
}

Creating TicTacToe in javafx

I am writing a TicTacToe program that displays a tic-tac-toe board that has the following qualities:
A cell may be X, O, or empty.
What to display at each cell is randomly decided upon startup of program.
Input the X's and O's as text instead of images.
In my program, I have the X's and O's as .gif files. I was wondering how the code would look when placing the X's and O's as text instead of images? Thanks in advance!
here is my code:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Text;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class TicTacToe extends Application {
#Override
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int random = (int)(Math.random() * 3);
if (random != 2) {
String text = (random > 0) ? "/image/x.gif" : "/image/o.gif";
pane.add(new ImageView(new Image(image)), j, i);
}
}
}
Scene scene = new Scene(pane, 150, 150);
primaryStage.setTitle("Tic Tac Toe");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
// Create a scene and place it in the stage
Scene scene = new Scene(pane);
primaryStage.setTitle("TicTacToe"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
launch(args);
}
}
Replace "/image/x.gif" with "X" and "/image/o.gif" with "O" and instead of using an ImageView, use a Label and set the text of the label to the text variable then add it to your Pane

Resources