我如何在controlsfx GridView for JavaFX中访问滚动位置?

问题描述

我正在JavaFX应用程序中使用controlsfx GridView。它在需要时显示滚动条,但是我找不到确定滚动条位置的方法,也无法更新它。我需要能够执行诸如响应用户“转到顶部”命令并向上滚动的操作;或滚动以使所选缩略图保持可见,因为用户使用箭头键在网格中导航。但是我没有看到如何访问当前的滚动位置,也没有像使用ScrollPane那样操纵它。

例如,这是一个示例应用程序,它创建了一个GridView,其中包含100个生成的图像。我在“ onScrollProperty”中添加一个侦听器,但从未调用过它。我也不知道如何使它滚动到某个滚动位置(0..1):

import java.awt.image.BufferedImage;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import org.controlsfx.control.GridView;
import org.controlsfx.control.cell.ImageGridCell;

// Demo class to illustrate the slowdown problem without worrying about thumbnail generation or fetching.
public class GridViewDemo extends Application {
  private static final int CELL_SIZE = 200;

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

  public void start(Stage primaryStage) {
    // Create a Scene with a ScrollPane that contains a TilePane.
    GridView<Image> gridView = new GridView<>();
    gridView.setCellFactory(gridView1 -> new ImageGridCell());
    gridView.setCellWidth(CELL_SIZE);
    gridView.setCellHeight(CELL_SIZE);
    gridView.setHorizontalCellSpacing(10);
    gridView.setVerticalCellSpacing(10);
    addImagesToGrid(gridView);

    gridView.onScrollproperty().addListener((observable,oldValue,newValue) -> {
      // Never called
      System.out.println("Scrolled...");
    });

    primaryStage.setScene(new Scene(gridView,1000,600));
    primaryStage.setonCloseRequest(x -> {
      Platform.exit();
      System.exit(0);
    });
    primaryStage.show();
  }

  private void addImagesToGrid(GridView<Image> gridView) {
    for (int i = 0; i < 100; i++) {
      final Image image = createFakeImage(i,CELL_SIZE);
      gridView.getItems().add(image);
    }
  }

  // Create an image with a bunch of rectangles in it just to have something to display.
  private static Image createFakeImage(int imageIndex,int size) {
    BufferedImage image = new BufferedImage(size,size,BufferedImage.TYPE_INT_RGB);
    Graphics g = image.getGraphics();
    for (int i = 1; i < size; i ++) {
      g.setColor(new Color(i * imageIndex % 256,i * 2 * (imageIndex + 40) % 256,i * 3 * (imageIndex + 60) % 256));
      g.drawRect(i,i,size - i * 2,size - i * 2);
    }
    return SwingFXUtils.toFXImage(image,null);
  }
}

所需的行家包括

    <dependency>
      <groupId>org.controlsfx</groupId>
      <artifactId>controlsfx</artifactId>
      <version>8.0.6_20</version>
    </dependency>

这是它的外观的屏幕截图。

GridView with scrollbar

解决方法

对于提问者来说可能迟到了。但是在我偶然发现同样的问题之后,经过数小时的调查,希望对其他人有用...

我向“onScrollProperty”添加了一个侦听器,但它从未被调用。

这“按预期工作”。 :-/ 见 https://bugs.openjdk.java.net/browse/JDK-8096847。 您必须使用“addEventFilter()”。请参阅下面的示例。

设置滚动位置很痛苦。您必须获得 GridView 的底层“VirtualFlow”对象。 VirtualFlow 包含将滚动位置设置为特定行的方法。奇怪的是 GridView 似乎没有针对这个常见用例的 API。 :-(

“概念证明”示例如何为带有图像的 GridView 设置滚动位置:

using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Player : MonoBehaviour
{

    public SpriteRenderer[] renderers;

    private void Start() {
        renderers[0].material.color = Color.red;
    }
}

(使用 javafx 15.0.1 和 controlsfx 11.0.3 测试)