Jen*_*gsa 6 javafx focus key-bindings scrollview javafx-8
我有一个ScrollPane包含可聚焦节点.
当前的默认行为是:
Shift+ ←,↑,→,↓将焦点移动
←,↑,→,↓滚动视图
我反过来想要它.我怎样才能完成这个或者我应该从哪里开始?
[编辑]嗯,还有另一个脆弱的方法.
人们可以乱用KeyBindings ,而不是乱搞事件.
scrollPane.skinProperty().addListener(new ChangeListener<Skin<?>>() {
@Override
public void changed(ObservableValue<? extends Skin<?>> observable, Skin<?> oldValue, Skin<?> newValue) {
ScrollPaneSkin scrollPaneSkin = (ScrollPaneSkin) scrollPane.getSkin();
ScrollPaneBehavior scrollPaneBehavior = scrollPaneSkin.getBehavior();
try {
Field keyBindingsField = BehaviorBase.class.getDeclaredField("keyBindings");
keyBindingsField.setAccessible(true);
List<KeyBinding> keyBindings = (List<KeyBinding>) keyBindingsField.get(scrollPaneBehavior);
List<KeyBinding> newKeyBindings = new ArrayList<>();
for (KeyBinding keyBinding : keyBindings) {
KeyCode code = keyBinding.getCode();
newKeyBindings.add(code == KeyCode.LEFT || code == KeyCode.RIGHT || code == KeyCode.UP || code == KeyCode.DOWN ? keyBinding.shift() : keyBinding);
}
keyBindingsField.set(scrollPaneBehavior, newKeyBindings);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
LOGGER.warn("private api changed.", e);
}
}
});
Run Code Online (Sandbox Code Playgroud)
我认为,如果KeyBindings更加非静态,可修改和公开,那么这可能是更清晰的方式.
使用事件过滤器捕获相关的关键事件,并在事件开始冒泡之前将它们重新映射到不同的关键事件。
重新映射默认键是一件棘手的事情:
所以请谨慎使用:
import javafx.application.*;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.TilePane;
import javafx.stage.Stage;
import java.util.*;
public class ScrollInterceptor extends Application {
@Override
public void start(Stage stage) {
ScrollPane scrollPane = new ScrollPane(
createScrollableContent()
);
Scene scene = new Scene(
scrollPane,
300, 200
);
remapArrowKeys(scrollPane);
stage.setScene(scene);
stage.show();
hackToScrollToTopLeftCorner(scrollPane);
}
private void remapArrowKeys(ScrollPane scrollPane) {
List<KeyEvent> mappedEvents = new ArrayList<>();
scrollPane.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (mappedEvents.remove(event))
return;
switch (event.getCode()) {
case UP:
case DOWN:
case LEFT:
case RIGHT:
KeyEvent newEvent = remap(event);
mappedEvents.add(newEvent);
event.consume();
Event.fireEvent(event.getTarget(), newEvent);
}
}
private KeyEvent remap(KeyEvent event) {
KeyEvent newEvent = new KeyEvent(
event.getEventType(),
event.getCharacter(),
event.getText(),
event.getCode(),
!event.isShiftDown(),
event.isControlDown(),
event.isAltDown(),
event.isMetaDown()
);
return newEvent.copyFor(event.getSource(), event.getTarget());
}
});
}
private TilePane createScrollableContent() {
TilePane tiles = new TilePane();
tiles.setPrefColumns(10);
tiles.setHgap(5);
tiles.setVgap(5);
for (int i = 0; i < 100; i++) {
Button button = new Button(i + "");
button.setMaxWidth(Double.MAX_VALUE);
button.setMaxHeight(Double.MAX_VALUE);
tiles.getChildren().add(button);
}
return tiles;
}
private void hackToScrollToTopLeftCorner(final ScrollPane scrollPane) {
Platform.runLater(new Runnable() {
@Override
public void run() {
scrollPane.setHvalue(scrollPane.getHmin());
scrollPane.setVvalue(0);
}
});
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3399 次 |
| 最近记录: |