我有一个ListView作为JavaFX分页控件的内容节点。
我的目的是在选择新页面后将焦点设置到ListView。
我的方法的问题是有时ListView具有焦点,但有时没有。

选择新页面后,如何确保ListView具有焦点?

平台:
Windows 7的
JDK 1.8.0.25(64位)

码:

package test.focus;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.Pagination;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class MainApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Pagination pagination = new Pagination(5);
        final ObservableList<String> texts = FXCollections.observableArrayList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
        final ListView<String> textsListView = new ListView<>();
        pagination.setPageFactory(new Callback<Integer, Node>() {

            @Override
            public Node call(Integer page) {
                textsListView.setItems(FXCollections.observableArrayList(texts.subList(page, page + 2)));
                textsListView.getSelectionModel().select(0);
                // Platform.runLater does not work, too
                textsListView.requestFocus();
                return textsListView;
            }
        });

        BorderPane root = new BorderPane(pagination);
        Scene scene = new Scene(root, 800, 600);

        stage.setTitle("Focus issue");
        stage.setScene(scene);
        stage.show();
    }

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

}

最佳答案

您需要两件事来始终将重点放在列表上:


pagination不应成为焦点遍历循环的一部分。
每当列表失去焦点时,都应再次请求它。


这对我有用:

    final ListView<String> textsListView = new ListView<>();
    textsListView.focusedProperty().addListener((ov,b,b1)->{
        if(!b1){
            textsListView.requestFocus();
        }
    });

    pagination.setFocusTraversable(false);
    pagination.setPageFactory(page -> {
        textsListView.setItems(
            FXCollections.observableArrayList(texts.subList(page, page + 2)));
        textsListView.getSelectionModel().select(0);

        textsListView.requestFocus();
        return textsListView;
    });


编辑

为了避免列表每次失去焦点时都请求焦点,此方法仅在加载新页面时才请求焦点:

    final ListView<String> textsListView = new ListView<>();
    final BooleanProperty loaded=new SimpleBooleanProperty(false);

    pagination.setFocusTraversable(false);
    pagination.setPageFactory(page -> {
        textsListView.setItems(
             FXCollections.observableArrayList(texts.subList(page, page + 2)));
        textsListView.getSelectionModel().select(0);

        loaded.set(true);
        return textsListView;
    });

    loaded.addListener((ov,b,b1)->{
        if(b1){
            textsListView.requestFocus();
            loaded.set(false);
        }
    });

07-28 01:07
查看更多