Bottom node in stackpane disappearing - java

Each stack pane is supposed to have two nodes. However the bottom node disappears outside the for loop for the first 2 indices in the stack pane array.
public class Main extends Application {
GridPane images;
StackPane[] stackPane;
ImageView cardBack;
ImageView[] cardImages;
#Override
public void start(Stage stage) throws FileNotFoundException {
images = new GridPane(); images.setAlignment(Pos.CENTER);
images.setVgap(5); images.setHgap(5);
cardBack = new ImageView(new Image(new FileInputStream("images/b1fv.gif")));
cardImages = new ImageView[]{
new ImageView(new Image(new FileInputStream("images/c1.gif"))),
new ImageView(new Image(new FileInputStream("images/c2.gif"))),
new ImageView(new Image(new FileInputStream("images/c3.gif")))
};
final Button[] flip = new Button[cardImages.length];
stackPane = new StackPane[cardImages.length];
for (int i = 0; i < cardImages.length; i++) {
stackPane[i] = new StackPane();
stackPane[i].getChildren().addAll(cardBack, cardImages[i]);
images.add(stackPane[i], i, 0, 1, 1);
flip[i] = new Button("Flip");
GridPane.setHalignment(flip[i], HPos.CENTER);
images.add(flip[i], i, 1, 1, 1);
// Debug
System.out.println(stackPane[i].getChildren().toString());
final int j = i;
flip[j].setOnAction(event -> doFlip(j));
}
// Debug
System.out.println("");
for (StackPane pane : stackPane)
System.out.println(pane.getChildren().toString());
stage.setTitle("Assignment 11");
stage.setScene(new Scene(images, 500,200));
stage.show();
}
void doFlip(int loc) {
// Debug
System.out.println("");
for (StackPane pane : stackPane)
System.out.println(pane.getChildren().toString());
ObservableList<Node> children = stackPane[loc].getChildren();
Node topNode = children.get(children.size()-1);
topNode.toBack();
}
public static void main(String[] args) {
launch(args);
}
}
[ImageView#5e1bc54a[styleClass=image-view], ImageView#25389181[styleClass=image-view]]
[ImageView#5e1bc54a[styleClass=image-view], ImageView#ff7cf97[styleClass=image-view]]
[ImageView#5e1bc54a[styleClass=image-view], ImageView#18b8669d[styleClass=image-view]]
[ImageView#25389181[styleClass=image-view]]
[ImageView#ff7cf97[styleClass=image-view]]
[ImageView#5e1bc54a[styleClass=image-view], ImageView#18b8669d[styleClass=image-view]]
[ImageView#25389181[styleClass=image-view]]
[ImageView#ff7cf97[styleClass=image-view]]
[ImageView#5e1bc54a[styleClass=image-view], ImageView#18b8669d[styleClass=image-view]]
Inside the for loop it displays all objects. However, outside the loop in does not display the bottom nodes except for the last element of array.

You cannot add the same Node instance to multiple parents!
In the top of your loop you have the following line:
stackPane[i].getChildren().addAll(cardBack, cardImages[i]);
The cardBack Node would be added to all StackPanes, but since it can only have one parent, it will be removed from the previous. Javafx has provided a way to reuse Image resources though (which is I imagine the thing you want to achieve). Instead of creating one ImageView, you can cache the Image instance passes in the ImageView constructor. E.g:
cardBack = new Image(new FileInputStream("images/b1fv.gif"));
// some stuff
for (int i = 0; i < cardImages.length; i++) {
stackPane[i] = new StackPane();
stackPane[i].getChildren().addAll(new ImageView(cardBack) , cardImages[i]);
// rest of the loop
}
If you use the Image and ImageView as described above, things will work correctly.

Related

JavaFX - Positioning image with character input

I have a GUI that takes the input of an image name, and once the refresh button is pressed, its displayed in a fixed position. I want to be able to input a character 'A-G' which will change the X position of the image, and a character '0-6' that will change the Y position of the image. The name of the images are just "A1", "A2"..."A5". So, if the user inputs "A1B3", it will display the image A1 in X-Position 'B' and Y-Position '3'. So B could be 200, and 3 could be 300, which makes the (X,Y) coordinates (200,300).
This is my code that gets the users input for the image.
private void getImage(){
Image img = new Image("comp1110/ass2/gui/assets/" + textField.getText() + ".png", 100, 100, false, false);
ImageView image = new ImageView();
image.setImage(img);
image.setX(100);
image.setY(100);
pane.getChildren().add(image);
}
I think you should do something along the lines of this yes there is some cosmetic issues that you will need to fix. But its only to give you an idea of what to do. It uses a gridpane so you don't have to worry about getting exact coordinates I choose a vbox so I didn't have to worry about layout you can keep the Pane that you have it shouldn't make a difference.
public class Main extends Application {
private GridPane gridPane;
private TextField imageTextField = new TextField();
private HashMap<String,String> hashMap = new HashMap<>();
#Override
public void start(Stage primaryStage) {
fillHashMapValues();
gridPane = new GridPane();
gridPane.setGridLinesVisible(true);
for (int i = 0; i < 7; i++) {
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.setPercentHeight(14);
gridPane.getRowConstraints().add(rowConstraints);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setPercentWidth(14);
gridPane.getColumnConstraints().add(columnConstraints);
gridPane.addColumn(i);
gridPane.addRow(i);
}
imageTextField.setPromptText("Enter Image Letters?");
TextField textField = new TextField();
textField.setPromptText("Enter Coordinates");
Button button = new Button("Go!");
button.setOnAction(event -> {
addToGridPane(textField.getText());
});
VBox vBox = new VBox();
vBox.setPrefSize(300, 300);
vBox.setAlignment(Pos.TOP_CENTER);
vBox.getChildren().addAll(imageTextField, textField, button, gridPane);
primaryStage.setScene(new Scene(vBox));
primaryStage.show();
button.requestFocus();//This is only so you can see the prompt text its irrelevant
}
private void fillHashMapValues(){
hashMap.put("A", "1");
hashMap.put("B", "2");
hashMap.put("C", "3");
hashMap.put("D", "4");
hashMap.put("E", "5");
hashMap.put("F", "6");
hashMap.put("G", "7");
}
private void addToGridPane(String string){
char[] chars = string.toCharArray();
if(chars.length==2){//Do more data validation here
if(hashMap.containsKey(String.valueOf(chars[0]))) {
int xValue = Integer.parseInt(hashMap.get(String.valueOf(chars[0])));
int yValue = Integer.parseInt(String.valueOf(chars[1]));
ImageView image = getImage();
gridPane.add(image, xValue, yValue);
}
}
}
private ImageView getImage(){
Image image = new Image("comp1110/ass2/gui/assets/" + imageTextField.getText() + ".png", 100, 100, false, false);
ImageView imageView = new ImageView();
imageView.setImage(image);
//imageView.setX(100);
//imageView.setY(100);
//pane.getChildren().add(image);
return imageView;
}
public static void main(String[] args) { launch(args); }
}

Displaying the images using a list of arrays in JavaFx

I am new to JAVAFX and I am creating a card game. I have a problem in displaying the pictures of the card on the screen.
I have card images in one folder in the JAVA Project and I am accessing it. But when I run the program I cannot see any images of the cards on the screen.
Here is my code.
public class Main extends Application
{
public static void main(String args[])
{
// launch the application
launch(args);
}
public void start(Stage s)
{
TilePane r = new TilePane();
Scene sc = new Scene(r);
List<Image>card = new ArrayList<>();
for(int i = 1; i < 4; i++)
{
card.add(new Image(getClass().getResource(i+".png").toExternalForm()));
}
ImageView view1 = new ImageView(card.get(1));
ImageView view2 = new ImageView(card.get(2));
ImageView view3 = new ImageView(card.get(3));
view1.setImage(card.get(1));
view2.setImage(card.get(2));
view3.setImage(card.get(3));
s.setScene(sc);
s.show();
}
}
Add the ImageViews to the TilePane and the TilePane to the Scene
TilePane r = new TilePane();
r.getChildren().addAll(view1,view2,view3);
Scene sc = new Scene(r);
s.setScene(sc);
s.show();

JavaFX CheckBoxTreeItem graphic disappear/appear when expanding/collapsing

I'm trying to make TreeView with CheckBoxTreeItems. When I collapse/expand a CheckBoxTreeItems the image I set up does not display correctly. I googled but I couldn't find correct answer. On Stack Overflow, I found a similar problem, but I didn't get a valid answer.
E.g
JavaFX CheckBoxTreeItem graphic disappear when siblings collapse
JavaFX CheckBoxTreeItem: Graphic disappears if graph is extended
Any ideas?
public class ClientApplication extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage stage) {
ImageView folderIcon = new ImageView();
Image folderImage = new Image("image/folder.png");
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", folderIcon);
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), folderIcon);
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
}
enter image description here
I tried to use the ideas provided by #Jai,But when I click the expand/collapse icon, there is still a problem.Attachment is a screenshot.Thanks in advance.
enter image description here
ImageView is a JavaFX control. This means that each instance represents a unique control you see on your screen. You should never use the same instance for multiple locations in your GUI.
On the other hand, Image represents an image (i.e. an array of pixel data), so it is reusable.
This should work:
#Override
public void start(final Stage stage) {
final Image folderImage = new Image("image/folder.png");
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem<String>("folder", createImageView(folderImage));
rootItem.setExpanded(true);
for (int i = 0; i < 4; i++) {
CheckBoxTreeItem<String> checkBoxTreeItem = new CheckBoxTreeItem<String>("Sample" + (i + 1), createImageView(folderImage));
rootItem.getChildren().add(checkBoxTreeItem);
}
final TreeView<String> tree = new TreeView<String>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.<String>forTreeView());
tree.setRoot(rootItem);
tree.setShowRoot(true);
StackPane root = new StackPane();
root.getChildren().add(tree);
stage.setScene(new Scene(root, 300, 250));
stage.show();
}
private ImageView createImageView(Image folderImage) {
ImageView folderIcon = new ImageView();
folderIcon.setImage(folderImage);
folderIcon.setFitWidth(16);
folderIcon.setFitHeight(16);
return folderIcon;
}

JavaFx pane in pane resizing

How I can resize Pane in GridPane? I'm creating a GUI which is GridPane and a map in it. And when gui change it's size I want to map which is in another Pane to resize. So I've added listners to width and height property of scene and there are generaly working. When I do setTranslateX of map I can see that something changed, but resizing not works at all. It can be caused by fact that map contains from tiles which have their size set. Code of method which create the scene:
private Scene createScene(GridPane root){
Scene scene = new Scene(root, WIDTH_OF_SCENE, HEIGHT_OF_SCENE);
scene.widthProperty().addListener((observableValue, oldSceneWidth, newSceneWidth) -> {
WIDTH_OF_SCENE = newSceneWidth.intValue();
draw();
MAP_PANE.setPrefSize(200, 200); //it's not working
MAP_PANE.setTranslateX(0); //it's working
root.requestLayout();
});
scene.heightProperty().addListener((observableValue, oldSceneHeight, newSceneHeight) ->{
HEIGHT_OF_SCENE = newSceneHeight.intValue();
draw();
root.requestLayout();
});
return scene;
}
And here I'm creating MAP_PANE:
public Pane createContent() {
map = new Pane();
map.setStyle("-fx-background-color: #383838");
// dodawanie pojedynczych kafli do dwuwymiarowej tablicy
for (int y = 0; y < Y_TILES; y++) {
for (int x = 0; x < X_TILES; x++) {
Tile tile = new Tile(x, y);
grid[x][y] = tile;
map.getChildren().addAll(tile);
}
}
return map;
}
And start method:
#Override
public void start(Stage primaryStage) throws Exception{
Map map = new Map();
GridPane root = FXMLLoader.load(getClass().getResource("sample.fxml"));
MAP_PANE = map.createContent();
IMAGE_VIEW = new ImageView();
countScreenSize();
draw();
root.getChildren().addAll(IMAGE_VIEW);
root.getChildren().addAll(MAP_PANE);
primaryStage.setTitle(TITLE);
primaryStage.setScene(createScene(root));
primaryStage.show();
}

Having trouble using getChildren()

Im working on a project for school and I'm having trouble adding a child pane to a parent pane. All the code compiles except when I get to the pane.getChildren().add(Matrix); . Im able to get the code to compile when I have all the code in main, but I really want to have main call a class and create the pane there then add it to the parent pane. Im not to worried about it looking pretty right now, just want to find a way to get it to work. If anyone could help get me going in the right direction I would really appreciate it.
The compiler gives me
Button1.java:34: error: identifier expected
pane.getChildren().add(Matrix);
Button1.java:34: error: ';' expected
pane.getChildren().add(Matrix);
public class Button1 extends Application {
public void start(Stage primaryStage) {
Scene scene = new Scene(pane, 700, 500);
primaryStage.setTitle("3 pains 1 window "); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
public static void main(String[] args) {
Application.launch(args);
}
GridPane pane = new GridPane();
MatrixPane Matrix = new MatrixPane();
pane.getChildren().add(Matrix);
}
class MatrixPane extends Pane {
double HEIGHT = 500;
double WIDTH = 200;
private GridPane pane = new GridPane();
public MatrixPane() {
}
public void fillpane() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
TextField text = new TextField(Integer.toString((int)(Math.random() * 2)));
text.setMinWidth(WIDTH / 8.0);
text.setMaxWidth(WIDTH / 10.0);
text.setMinHeight(HEIGHT / 8.0);
text.setMaxHeight(HEIGHT / 10.0);
pane.add(text, j, i);
}
}
}
}
That line have to be inside of a method, I suggest that it should be inside of start
public void start(Stage primaryStage) {
pane.getChildren().add(Matrix);
...
You have missed to include the following section inside a method().

Categories