JavaFX GridView 如何获取可见元素的 id

问题描述 投票:0回答:1

我正在尝试获取填充有图像的 GridView 当前可见单元格/行索引。

我找到了从侦听器中取出 id 的方法,但是当我开始在图像上添加文本/标签并将其作为

StackPane
GridView
而不是
Images
时,它停止工作(类强制转换异常
IndexedCell
)。

这是主课:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import javafx.stage.Stage;


public class MainApp extends Application {
    public MyGridView myGridView;


    @Override
    public void start(final Stage primaryStage) {

        myGridView = new MyGridView();

        HBox row1 = new HBox(myGridView);
        HBox.setHgrow(myGridView, Priority.ALWAYS);

        Scene scene = new Scene(row1, 1200, 800, Color.BLACK);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }


} 

这是

MyGridView
课程:


import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.IndexedCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import org.controlsfx.control.GridCell;
import org.controlsfx.control.GridView;
import org.controlsfx.control.cell.ImageGridCell;

import java.awt.*;
import java.awt.image.BufferedImage;



public class MyGridView extends GridView {
    public static final int GRID_CELL_WIDTH = 512;
    public static final int GRID_CELL_HEIGHT = 360;
    public static final int GRID_CELL_SPACING_HORIZONTAL = 5;
    public static final int GRID_CELL_SPACING_VERTICAL = 5;

    public MyGridView() {
        setCellWidth(GRID_CELL_WIDTH);
        setCellHeight(GRID_CELL_HEIGHT);
        setHorizontalCellSpacing(GRID_CELL_SPACING_HORIZONTAL);
        setVerticalCellSpacing(GRID_CELL_SPACING_VERTICAL);

        addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
            Node clickedNode = e.getPickResult().getIntersectedNode();
            IndexedCell index = ((IndexedCell) clickedNode);
            int clickedItemId = index.getIndex();
            System.out.println("Clicked id = " + clickedItemId);
        });

        addEventFilter(ScrollEvent.ANY, e -> {
            Node clickedNode = e.getPickResult().getIntersectedNode();
            System.out.println(clickedNode.getClass());
            IndexedCell index = ((IndexedCell) clickedNode);
            int clickedItemId = index.getIndex();
            System.out.println("Scrolled id = " + clickedItemId);
        });


        //scroll/click cells is working with this, comment it and uncomment next one
        setCellFactoryWorking();
//        setCellFactoryNotWorking();

        addImagesToGrid(this);

    }

    private void setCellFactoryWorking() {
        setCellFactory(gv -> new GridCell<Image>() {
            private final ImageView imageView = new ImageView();

            {
                imageView.setFitHeight(GRID_CELL_HEIGHT);
                imageView.setPreserveRatio(true);
            }

            @Override
            protected void updateItem(Image image, boolean empty) {
                super.updateItem(image, empty);
                imageView.setImage(image);
                setGraphic(imageView);

            }
        });
    }

    private void setCellFactoryNotWorking() {
        setCellFactory(gv -> new GridCell<Image>() {
            private final ImageView imageView = new ImageView();

            {
                imageView.setFitHeight(GRID_CELL_HEIGHT);
                imageView.setPreserveRatio(true);
            }

            @Override
            protected void updateItem(Image image, boolean empty) {
                super.updateItem(image, empty);
                imageView.setImage(image);
                Text text = new Text("  Lorem Ipsum");
                text.setFill(javafx.scene.paint.Color.rgb(255, 255, 255));
                StackPane pane = new StackPane();
                pane.getChildren().add(imageView);
                pane.getChildren().add(text);
                pane.setAlignment(Pos.TOP_LEFT);
                setGraphic(pane);

            }
        });
    }

    private void addImagesToGrid(GridView<Image> gridView) {
        for (int i = 1; i < 200; i++) {
            final Image image = createFakeImage(i, GRID_CELL_WIDTH, GRID_CELL_HEIGHT);
            gridView.getItems().add(image);
        }
    }


    private static Image createFakeImage(int imageIndex, int width, int height) {
        BufferedImage image = new BufferedImage(width, width, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        for (int i = 1; i < width; i++) {
            g.setColor(new Color(i * imageIndex % 256, i * 2 * (imageIndex + 40) % 256, i * 3 * (imageIndex + 60) % 256));
            double proportion = width / height;
            g.drawRect(i, i, width - i * 2, (int) ((width - i * 2) * proportion));
        }


        return SwingFXUtils.toFXImage(image, null);
    }
}

如果将

setCellFactoryWorking()
功能切换为
setCellFactoryNotWorking()
,您将看到鼠标悬停的参考类已更改,并且 id 中不再存在
IndexedCell
。实际上,这是检测
GridView
的实际可见元素的一种不好的方法,是否有更通用的方法不依赖于单元格元素类类型,并且可以告诉:

  • 可见行 ID

  • 可见单元格的id

  • 如果用鼠标单击单元格,那么它也是 id

  • 也很高兴知道鼠标悬停在其上的单元格 ID

java javafx gridview controlsfx
1个回答
0
投票

我在搜索过程中没有看到任何表明您可以获得行 ID 或列 ID 的内容。如您所知,您可以获得索引。我不确定为什么在将

Labels
Images
\
ImageViews
添加到
StackPane
时出现错误。下面是一个示例,它将在输入、退出或单击时提供单元格的 ID 和索引。您有代表一个细胞的模型吗?此示例使用带有图像和字符串的模型来表示单元格。

主要

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import org.controlsfx.control.GridCell;
import org.controlsfx.control.GridView;

public class App extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    public static final int GRID_CELL_WIDTH = 50;
    public static final int GRID_CELL_HEIGHT = 50;
    public static final int GRID_CELL_SPACING_HORIZONTAL = 5;
    public static final int GRID_CELL_SPACING_VERTICAL = 5;
    
    List<Color> defaultColors = getAllDefaultColors();
    
    @Override
    public void start(Stage primaryStage) {    
        ObservableList<ImageModel> modelList = FXCollections.observableArrayList();
        for(int i = 1; i <= 1000; i++)
        {
            modelList.add(new ImageModel(i, createFakeImage(GRID_CELL_WIDTH, GRID_CELL_HEIGHT)));
        }
        
        GridView<ImageModel> gridView = new GridView();
        gridView.setCellWidth(GRID_CELL_WIDTH);
        gridView.setCellHeight(GRID_CELL_HEIGHT);
        gridView.setHorizontalCellSpacing(GRID_CELL_SPACING_HORIZONTAL);
        gridView.setVerticalCellSpacing(GRID_CELL_SPACING_VERTICAL);
        
        gridView.setItems(modelList);
        gridView.setCellFactory((GridView<ImageModel> param) -> {
            GridCell<ImageModel> cell = new GridCell<ImageModel>() {                
                ImageView imageView = new ImageView();
                Label label = new Label();
                StackPane spRoot = new StackPane(imageView, label);
                
                @Override
                protected void updateItem(ImageModel item, boolean empty) {
                    super.updateItem(item, empty);
                    if (item != null) {
                        label.setText(Integer.toString(item.getId()));
                        imageView.setImage(item.getImage());                          
                        
                        setOnMouseClicked((mouseEvent) -> {                            
                            System.out.println("Clicked: index-" + getIndex() + "\tID-" + item.getId());
                            mouseEvent.consume();
                        });
                        
                        setOnMouseEntered((mouseEvent) -> {                            
                            System.out.println("Entered: index-" + getIndex() + "\tID-" + item.getId());
                            mouseEvent.consume();
                        });
                        
                        setOnMouseExited((mouseEvent) -> {                            
                            System.out.println("Exited: index-" + getIndex() + "\tID-" + item.getId());
                            mouseEvent.consume();
                        });
                        
                        setGraphic(spRoot);
                    } else {
                        setText("");
                        setGraphic(null);
                    }
                }
            };
            
            return cell;
        });
        
        StackPane root = new StackPane(gridView);
        Scene scene = new Scene(root, 1080, 720);
        primaryStage.setScene(scene);
        primaryStage.setTitle("JavaFX App");
        primaryStage.show();
    }    
    
    private Image createFakeImage(int width, int height) {
        Color currentColor = defaultColors.get(ThreadLocalRandom.current().nextInt(defaultColors.size()));
        
        WritableImage writableImage = new WritableImage(width, height);
        PixelWriter pixelWriter = writableImage.getPixelWriter();

        for(int x = 0; x < width; x++)
        {
            for(int y = 0; y < height; y++)
            {
                pixelWriter.setColor(x, y, currentColor);
            }
        }
        
        return writableImage;
    }
    
    private List<Color> getAllDefaultColors(){
        List<Color> colors = new ArrayList<>();
        
        try 
        {
            
            Class clazz = Class.forName("javafx.scene.paint.Color");
            if (clazz != null) {
                Field[] field = clazz.getFields();
                for (Field f : field) {
                    Object obj = f.get(null);
                    if(obj instanceof Color){
                        colors.add((Color) obj);
                    }
                }
            }
            
        } catch (ClassNotFoundException | IllegalArgumentException | IllegalAccessException ex) {
            System.out.println(ex.toString());
        } 
        
        return colors;
    }
}

图像模型

import javafx.scene.image.Image;

/**
 *
 * @author sedj601
 */
public class ImageModel {
    private int id;
    private Image image;

    public ImageModel(int id, Image image) {
        this.id = id;
        this.image = image;
    }

    public Image getImage() {
        return image;
    }

    public void setImage(Image image) {
        this.image = image;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }    
}

输出

我没有发布输出 GIF,因为 StackOverflow 已将接受的图像尺寸减小到 50 兆像素。

© www.soinside.com 2019 - 2024. All rights reserved.