How can I change a label that is on a javafx gridpane

Asked

Viewed 496 times

1

Good afternoon community,

Lately I’ve been exploring the javafx aspect and creating an application for my master’s degree. Briefly, the application receives an image from the user, and creates a gridpane above the image, depending on the number of columns and rows the user wants. Each gridpane cell has a label value of 0.

The image is an example of the explanation: inserir a descrição da imagem aqui

So far so good. What I want and am not succeeding, is to add an Event mouse, that whenever I click on a gridpane label/cell, the value 0 passes to 1.

package vistas;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ResourceBundle;

import javax.print.DocFlavor.URL;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.RowConstraints;
import javafx.stage.FileChooser;
import principal.main;

public class AreaProjectoController {

    @FXML
    private Button meuBotaoImagem, meuBotaoGrelha, btnLimpaGrelha;

    @FXML
    private ImageView minhaImagem;

    @FXML
    private TextField txtGrelhaLeft, txtGrelhaRight;

    @FXML
    private AnchorPane painelGrelha, painelArea;

    @FXML
    private GridPane painelCriaGrelha;

    public void initialize(URL location, ResourceBundle resources) {}

    public void mostraImagem(ActionEvent evento) throws FileNotFoundException {

        FileChooser imagemEscolhida = new FileChooser();

        // Define a extensão do ficheiro
        FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("JPEG/PNG", "*.jpeg", "*.png");
        imagemEscolhida.getExtensionFilters().add(extFilter);

        // abre a janela para procurar uma imagem
        File ficheiro = imagemEscolhida.showOpenDialog(main.getPrimaryStage());

        // O if trata quando se cancela o carregamento de uma imagem
        if(ficheiro != null) {
            Image imagem = new Image(new FileInputStream(ficheiro));
            minhaImagem.setImage(imagem);
            painelGrelha.setVisible(true);
            txtGrelhaLeft.setText("0");
            txtGrelhaRight.setText("0");
        } 

    }

    public void criaGrelha(ActionEvent evento) {

        int txtLeft = 0, txtRight = 0, i = 1, ii = 1;

        ColumnConstraints colunas = null; 
        RowConstraints linhas = null;

        txtLeft = Integer.parseInt(txtGrelhaLeft.getText());
        txtRight = Integer.parseInt(txtGrelhaRight.getText());

        //Este for cria a grelha após receber os valores
        for(i = 1; i <= txtLeft; i++) {
            colunas = new ColumnConstraints();
            colunas.setPercentWidth(25);
            painelCriaGrelha.getColumnConstraints().add(colunas);
        }

        for(ii = 1; ii <= txtRight; ii++) {
            linhas = new RowConstraints();
            linhas.setPercentHeight(25);
            painelCriaGrelha.getRowConstraints().add(linhas);
        }

        Label fillLabel[][] = new Label[txtLeft][txtRight];

        for (int l = 0; l < fillLabel.length; l++) {
            for (int j = 0; j < fillLabel[l].length; j++) {
                fillLabel[l][j] = new Label();
                fillLabel[l][j].setText("0");
                painelCriaGrelha.add(fillLabel[l][j], l, j);
            }
        }

        painelCriaGrelha.setGridLinesVisible(true); //isto faz aparecer as linhas da grelha a preto
        painelArea.setVisible(true);

        System.out.println(fillLabel[2][2]);
    }

    public void limpaGrelha(ActionEvent evento) {

        painelCriaGrelha.getColumnConstraints().clear();
        painelCriaGrelha.getRowConstraints().clear();
        txtGrelhaLeft.setText("0");
        txtGrelhaRight.setText("0");

    }


}

This is the code that has the features that we see in the image. It’s the view controller class. Because my goal is to select the cells/cells that correspond to the blue area of the image. Note that the values go to a matrix. In this example the matrix is:

0000000000

0000000000

0000000000

0000000000

0000000000

0000000000

0000000000

0000000000

0000000000

0000000000

But it should be, after implementing the mouse click event, something like this:

0000111111

1111111111

1111111111

1111100011

1111100011

0000000000

0000000000

0000000000

0000000000

0000000000

Thank you.

1 answer

0


I researched a lot about your problem and the solutions I found involved navigating all grid nodes and putting a onMouseClick on all nodes (Well pig in my opinion). As I did not find what seems most correct for your case I did a workaround that can solve your problem (Or at least a good direction).

@FXML
private GridPane grid;

private ObservableList<ColumnConstraints> columns;
private ObservableList<RowConstraints> rows;


@Override
public void initialize(URL url, ResourceBundle rb) {
    grid.setGridLinesVisible(true);
    columns = grid.getColumnConstraints();
    rows = grid.getRowConstraints();
}

@FXML
public void mudarValorCelula(MouseEvent e){
    Double x, y, columnAcc = 0.0, rowAcc = 0.0;
    int i = 0, j = 0;

    // Pega a posição clicada pelo mouse
    x = e.getX();
    y = e.getY();

    // Calcula em qual coluna o X está
    for (ColumnConstraints c : columns){
        if(columnAcc < x && x < columnAcc + c.getPrefWidth()){
            break;
        }
        j++;
        columnAcc += c.getPrefWidth();           
    }

    // Calcula em qual linha o Y está
    for (RowConstraints c : rows){
        if(rowAcc < y && y < rowAcc + c.getPrefHeight()){
            break;
        }
        i++;
        rowAcc += c.getPrefHeight();           
    }

    // Modificando o elemento correto
    Label l = (Label) grid.getChildren().get(j*columns.size() + i);
    l.setText("1");
}

You also need to put the changeValorCellle method on your grid onMouseClick:

<GridPane fx:id="grid" layoutX="15.0" layoutY="55.0" onMouseClicked="#mudarValorCelula">

This solution presupposes some important things:

  1. Your grid is fully filled with Labels
  2. The cells are in column order (see image below)
  3. All Rows and columns must have their Constraint

This is because the grid add method is like this grid.add(column, row) which is the opposite of what we’re used to, so we have to put the Abels in that order:

inserir a descrição da imagem aqui

If you want to take by Row you have to stay like this (0,0) (1,0) (2,0) (0,1) ... and change i*Columns.size() + j

Note: Only tested with square matrices, does not work for other types.

Note 2: If you know the number of columns the prioi It is good to put in place of Columns.size()

The result was the following:

inserir a descrição da imagem aqui

Browser other questions tagged

You are not signed in. Login or sign up in order to post.