簡體   English   中英

如何訪問 JavaFX 的 controlfx GridView 中的滾動位置?

[英]How can I access scroll position in controlsfx GridView for JavaFX?

我在 JavaFX 應用程序中使用了controlfx 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);
  }
}

所需的 Maven 包括:

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

這是它的外觀的屏幕截圖。

帶滾動條的 GridView

對於提問者來說可能為時已晚。 但是在我偶然發現同樣的問題之后,經過數小時的調查,希望對其他人有用......

我向“onScrollProperty”添加了一個偵聽器,但從未調用過它。

這“按預期工作”。 :-/ 見https://bugs.openjdk.java.net/browse/JDK-8096847 您必須使用“ addEventFilter() ”。 請參閱下面的示例。

設置滾動位置很痛苦。 您必須獲得 GridView 的底層“ VirtualFlow ”對象。 VirtualFlow 包含將滾動位置設置為特定行的方法。 奇怪的是 GridView 似乎沒有針對這個常見用例的 API。 :-(

“概念證明”示例如何為帶有圖像的 GridView 設置滾動位置:

/**
 * Register a scroll event and a key event listener to gridView. 
 * After that navigate with "arrow up" and "arrow down" the grid.
 * @param gridView 
 */
private void addScrollAndKeyhandler(final GridView<Image> gridView) {
    // example for scroll listener
    gridView.addEventFilter(ScrollEvent.ANY, e-> System.out.println("*** scroll event fired ***"));
    
    // add UP and DOWN arrow key listener, to set scroll position 
    gridView.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
        if (e.getCode() == KeyCode.UP) oneRowUp(gridView);
        if (e.getCode() == KeyCode.DOWN) oneRowDown(gridView);
    });
}

int selectedRow = 0; // current "selected" GridView row.
/**
 * Scrolls the GridView one row up.
 * @param gridView
 */
private void oneRowUp(final GridView<Image> gridView) {
    // get the underlying VirtualFlow object
    VirtualFlow<?> flow =  (VirtualFlow<?>) ((GridViewSkin<?>) gridView.getSkin()).getChildren().get(0);
    if (flow.getCellCount() == 0) return; // check that rows exist
    
    if (--selectedRow < 0) selectedRow = 0;
    if (selectedRow >= flow.cellCountProperty().get()) selectedRow =  flow.getCellCount() - 1;
    System.out.println("*** KeyEvent oneRowUp " + selectedRow + " ***"); 
    
    flow.scrollTo(selectedRow);
}

/**
 * Scrolls the GridView one row down.
 * @param gridView
 */
private void oneRowDown(final GridView<Image> gridView) {
    // get the underlying VirtualFlow object
    VirtualFlow<?> flow =  (VirtualFlow<?>) ((GridViewSkin<?>) gridView.getSkin()).getChildren().get(0);
    if (flow.getCellCount() == 0) return; // check that rows exist
    
    if (++selectedRow >= flow.cellCountProperty().get()) selectedRow =  flow.getCellCount() - 1;
    System.out.println("*** KeyEvent oneRowDown " + selectedRow + " ***");
    
    flow.scrollTo(selectedRow);
}

(使用 javafx 15.0.1 和 controlsfx 11.0.3 測試)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM