2016-12-05 67 views
2

我有一个ScrollPane,其中包含一个显示图像的TilePane。每当我删除其中一张图像时,ScrollPane会跳回到顶部,这在尝试删除多张图像时非常烦人。有没有办法控制滚动行为?ScrollPane在删除节点时跳转至顶部

我在Windows 7上运行此代码:

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.image.ImageView; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.StackPane; 
import javafx.scene.layout.TilePane; 
import javafx.stage.Stage; 

public class ScrollbarProblem extends Application{ 
    private TilePane imagePane; 
    private ScrollPane scroller; 

    @Override 
    public void start(Stage primaryStage) { 
     imagePane = new TilePane(); 
     scroller = new ScrollPane(); 
     scroller.setContent(imagePane); 
     BorderPane root = new BorderPane(scroller, null, null, null, null); 
     Scene scene = new Scene(root, 800, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     for(int i = 0; i < 20; i++){ 
      Image img = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/SIPI_Jelly_Beans_4.1.07.tiff/lossy-page1-220px-SIPI_Jelly_Beans_4.1.07.tiff.jpg"); 
      final ImageView imageView = new ImageView(img); 

      final Button button = new Button("Delete"); 
      final StackPane stackPane = new StackPane(); 

      button.setOnAction(new EventHandler<ActionEvent>() { 

       @Override 
       public void handle(ActionEvent event) { 
        imagePane.getChildren().remove(stackPane); 
       } 
      }); 

      stackPane.getChildren().addAll(imageView, button); 
      imagePane.getChildren().add(stackPane); 
     } 
    } 

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

这听起来有些不可思议.. 。你可以[编辑]你的问题来包含一个显示问题的[MCVE]吗? –

+0

我编辑了一个小例子。 – Simoon

回答

2

ScrollPane确保聚焦Node是视内部显示。被点击的Button具有焦点。这意味着焦点节点将被删除,并且JavaFX会尝试将焦点移动到ScrollPane内容中的另一个节点,在本例中为第一个ButtonScrollPane将此节点滚动到视图中,这解释了观察到的行为。

解决方法是将每个ButtonfocusTraversable属性设置为false

另一种选择这将仍然允许您通过标签将被重写ScrollPaneSkinonTraverse方法改变焦点,因为这是负责此行为的方法:

scroller.setSkin(new ScrollPaneSkin(scroller) { 

    @Override 
    public void onTraverse(Node n, Bounds b) { 
    } 

}); 
+0

由于通过按钮切换并不意味着您的解决方案更容易。谢谢! – Simoon

2

这个问题似乎由焦点恢复到按钮在瓦窗格中的第一个元素引起的。一个解决办法是:

Image img = new Image(
     "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/SIPI_Jelly_Beans_4.1.07.tiff/lossy-page1-220px-SIPI_Jelly_Beans_4.1.07.tiff.jpg"); 

for (int i = 0; i < 20; i++) { 
    final ImageView imageView = new ImageView(img); 

    final Button button = new Button("Delete"); 
    final StackPane stackPane = new StackPane(); 


    button.setOnAction(new EventHandler<ActionEvent>() { 

     @Override 
     public void handle(ActionEvent event) { 

      int index = imagePane.getChildren().indexOf(stackPane); 

      imagePane.getChildren().remove(index); 
      int numPanes = imagePane.getChildren().size(); 
      if (numPanes > 0) { 
       imagePane.getChildren().get(Math.min(index, numPanes-1)).requestFocus(); 
      } 
     } 
    }); 

    stackPane.getChildren().addAll(imageView, button); 
    imagePane.getChildren().add(stackPane); 
} 
+0

这是问题所在。谢谢! – Simoon