mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-11 12:56:53 -04:00
模组列表页中按下 Esc 时取消选中 (#3523)
* 模组列表页中按下 Esc 时取消选中
目前在模组列表页中选中模组后,按下 Esc 是不会有任何反应的,因为 [ListView](5b074c4c2b/modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/behavior/ListViewBehavior.java (L108)
) 会处理这个事件,认为是取消编辑,而不论是否处于编辑模式中。
这个 PR 添加了 `FXUtils.ignoreEvent()` 函数,用于忽略掉对特定事件的处理。然后,我们就可以让 ListView 不处理 Esc 按下事件,然后在模组页添加 Esc 处理逻辑(必须让 ListView 忽略掉这个事件,不然就会被它优先处理)。
理论上所有用了 ListView / JFXListView 的地方都会有这个问题,即当焦点在 ListView 中时,按下 Esc 不会触发正常的事件处理(如返回上一页、关闭对话框)。比如在游戏下载页面中,对某个版本按下右键后,焦点就会转移到其上,此时再按 Esc 就毫无反应。
* 修复 Esc 在版本下载页/模组下载页/数据包页不工作
This commit is contained in:
parent
01f9a452f1
commit
72d8b75643
@ -27,6 +27,9 @@ import javafx.beans.WeakInvalidationListener;
|
|||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.value.*;
|
import javafx.beans.value.*;
|
||||||
|
import javafx.event.Event;
|
||||||
|
import javafx.event.EventDispatcher;
|
||||||
|
import javafx.event.EventType;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.Cursor;
|
import javafx.scene.Cursor;
|
||||||
@ -86,6 +89,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.function.BooleanSupplier;
|
import java.util.function.BooleanSupplier;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -234,6 +238,21 @@ public final class FXUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T extends Event> void ignoreEvent(Node node, EventType<T> type, Predicate<? super T> filter) {
|
||||||
|
EventDispatcher oldDispatcher = node.getEventDispatcher();
|
||||||
|
node.setEventDispatcher((event, tail) -> {
|
||||||
|
EventType<?> t = event.getEventType();
|
||||||
|
while (t != null && t != type)
|
||||||
|
t = t.getSuperType();
|
||||||
|
if (t == type && filter.test((T) event)) {
|
||||||
|
return tail.dispatchEvent(event);
|
||||||
|
} else {
|
||||||
|
return oldDispatcher.dispatchEvent(event, tail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static <K, T> void setupCellValueFactory(JFXTreeTableColumn<K, T> column, Function<K, ObservableValue<T>> mapper) {
|
public static <K, T> void setupCellValueFactory(JFXTreeTableColumn<K, T> column, Function<K, ObservableValue<T>> mapper) {
|
||||||
column.setCellValueFactory(param -> {
|
column.setCellValueFactory(param -> {
|
||||||
if (column.validateValue(param))
|
if (column.validateValue(param))
|
||||||
|
@ -29,6 +29,8 @@ import javafx.geometry.Insets;
|
|||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ListCell;
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||||
@ -66,6 +68,7 @@ import java.util.function.Predicate;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap;
|
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap;
|
||||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||||
@ -150,6 +153,9 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
|
|||||||
list.getStyleClass().add("jfx-list-view-float");
|
list.getStyleClass().add("jfx-list-view-float");
|
||||||
VBox.setVgrow(list, Priority.ALWAYS);
|
VBox.setVgrow(list, Priority.ALWAYS);
|
||||||
|
|
||||||
|
// ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here
|
||||||
|
ignoreEvent(list, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE);
|
||||||
|
|
||||||
centrePane.getContent().setAll(checkPane, list);
|
centrePane.getContent().setAll(checkPane, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ import javafx.geometry.Insets;
|
|||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.SelectionMode;
|
import javafx.scene.control.SelectionMode;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
@ -38,6 +40,7 @@ import org.jackhuang.hmcl.ui.construct.SpinnerPane;
|
|||||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent;
|
||||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton;
|
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
|
|
||||||
@ -110,6 +113,9 @@ class DatapackListPageSkin extends SkinBase<DatapackListPage> {
|
|||||||
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
Bindings.bindContent(listView.getItems(), skinnable.getItems());
|
Bindings.bindContent(listView.getItems(), skinnable.getItems());
|
||||||
|
|
||||||
|
// ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here
|
||||||
|
ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE);
|
||||||
|
|
||||||
center.setContent(listView);
|
center.setContent(listView);
|
||||||
root.setCenter(center);
|
root.setCenter(center);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.control.Skin;
|
import javafx.scene.control.Skin;
|
||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.*;
|
import javafx.scene.layout.*;
|
||||||
import org.jackhuang.hmcl.game.Version;
|
import org.jackhuang.hmcl.game.Version;
|
||||||
import org.jackhuang.hmcl.mod.RemoteMod;
|
import org.jackhuang.hmcl.mod.RemoteMod;
|
||||||
@ -64,6 +66,7 @@ import java.util.Locale;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
|
import static org.jackhuang.hmcl.ui.FXUtils.stringConverter;
|
||||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.selectedItemPropertyFor;
|
||||||
@ -493,6 +496,9 @@ public class DownloadListPage extends Control implements DecoratorPage, VersionP
|
|||||||
RemoteMod selectedItem = listView.getSelectionModel().getSelectedItem();
|
RemoteMod selectedItem = listView.getSelectionModel().getSelectedItem();
|
||||||
Controllers.navigate(new DownloadPage(getSkinnable(), selectedItem, getSkinnable().getProfileVersion(), getSkinnable().callback));
|
Controllers.navigate(new DownloadPage(getSkinnable(), selectedItem, getSkinnable().getProfileVersion(), getSkinnable().callback));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ListViewBehavior would consume ESC pressed event, preventing us from handling it, so we ignore it here
|
||||||
|
ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE);
|
||||||
listView.setCellFactory(x -> new FloatListCell<RemoteMod>(listView) {
|
listView.setCellFactory(x -> new FloatListCell<RemoteMod>(listView) {
|
||||||
TwoLineListItem content = new TwoLineListItem();
|
TwoLineListItem content = new TwoLineListItem();
|
||||||
ImageView imageView = new ImageView();
|
ImageView imageView = new ImageView();
|
||||||
|
@ -31,6 +31,8 @@ import javafx.scene.control.SelectionMode;
|
|||||||
import javafx.scene.control.SkinBase;
|
import javafx.scene.control.SkinBase;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
@ -70,6 +72,7 @@ import java.util.function.Predicate;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.ignoreEvent;
|
||||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton2;
|
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.createToolbarButton2;
|
||||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||||
@ -170,6 +173,16 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
changeToolbar(toolbarSelecting);
|
changeToolbar(toolbarSelecting);
|
||||||
});
|
});
|
||||||
root.getContent().add(toolbarPane);
|
root.getContent().add(toolbarPane);
|
||||||
|
|
||||||
|
// Clear selection when pressing ESC
|
||||||
|
root.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
|
||||||
|
if (e.getCode() == KeyCode.ESCAPE) {
|
||||||
|
if (listView.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
listView.getSelectionModel().clearSelection();
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -196,6 +209,10 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ListViewBehavior would consume ESC pressed event, preventing us from handling it
|
||||||
|
// So we ignore it here
|
||||||
|
ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE);
|
||||||
|
|
||||||
center.setContent(listView);
|
center.setContent(listView);
|
||||||
root.getContent().add(center);
|
root.getContent().add(center);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user