-
Notifications
You must be signed in to change notification settings - Fork 814
使用 JFXListView 显示实例列表 #5174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
使用 JFXListView 显示实例列表 #5174
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request refactors the game instance list display to use JFXListView instead of custom Control-based implementations. The changes modernize the UI architecture by replacing custom skin-based controls with standard JavaFX ListView cells.
Changes:
- Introduces
GameListPopupMenuusing JFXListView for displaying game instances in a popup - Replaces custom skin classes (
GameListItemSkin,GameItemSkin) withGameListCellfor ListView-based rendering - Refactors
GameItemfrom a Control to a plain data class with lazy property initialization - Adds
ToolbarListPageSkin2as a new skin implementation for list pages using JFXListView
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| GameListPopupMenu.java | New popup menu component using JFXListView to display game instances |
| GameListCell.java | New ListCell implementation replacing GameListItemSkin for rendering game list items |
| ToolbarListPageSkin2.java | New skin base class for toolbar list pages using JFXListView |
| GameListPage.java | Simplified game list loading logic, removed ToggleGroup usage, switched to static nested class |
| GameListItem.java | Refactored to extend GameItem, removed custom skin, simplified selection binding |
| GameItem.java | Converted from Control to data class with lazy property initialization and updated copyright year |
| MainPage.java | Updated to use new GameListPopupMenu instead of PopupMenu |
| WeakListenerHolder.java | Added clear() method for cleanup |
| GameListItemSkin.java | Deleted - functionality moved to GameListCell |
| GameItemSkin.java | Deleted - no longer needed as GameItem is not a Control |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java
Outdated
Show resolved
Hide resolved
| private void preparePopupMenu(GameListItem item) { | ||
| this.getListView().getProperties().put(POPUP_ITEM_KEY, item); | ||
| } | ||
|
|
||
| private static Runnable getAction(ListView<GameListItem> listView, Consumer<GameListItem> action) { | ||
| return () -> { | ||
| if (listView.getProperties().get(POPUP_ITEM_KEY) instanceof GameListItem item) { | ||
| action.accept(item); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| private static JFXPopup getPopup(ListView<GameListItem> listView) { | ||
| return (JFXPopup) listView.getProperties().computeIfAbsent(GameListCell.class.getName() + ".popup", k -> { | ||
| PopupMenu menu = new PopupMenu(); | ||
| JFXPopup popup = new JFXPopup(menu); | ||
|
|
||
| menu.getContent().setAll( | ||
| new IconedMenuItem(SVG.ROCKET_LAUNCH, i18n("version.launch.test"), getAction(listView, GameListItem::testGame), popup), | ||
| new IconedMenuItem(SVG.SCRIPT, i18n("version.launch_script"), getAction(listView, GameListItem::generateLaunchScript), popup), | ||
| new MenuSeparator(), | ||
| new IconedMenuItem(SVG.SETTINGS, i18n("version.manage.manage"), getAction(listView, GameListItem::modifyGameSettings), popup), | ||
| new MenuSeparator(), | ||
| new IconedMenuItem(SVG.EDIT, i18n("version.manage.rename"), getAction(listView, GameListItem::rename), popup), | ||
| new IconedMenuItem(SVG.FOLDER_COPY, i18n("version.manage.duplicate"), getAction(listView, GameListItem::duplicate), popup), | ||
| new IconedMenuItem(SVG.DELETE, i18n("version.manage.remove"), getAction(listView, GameListItem::remove), popup), | ||
| new IconedMenuItem(SVG.OUTPUT, i18n("modpack.export"), getAction(listView, GameListItem::export), popup), | ||
| new MenuSeparator(), | ||
| new IconedMenuItem(SVG.FOLDER_OPEN, i18n("folder.game"), getAction(listView, GameListItem::browse), popup)); | ||
|
|
||
| popup.setOnHidden(event -> listView.getProperties().remove(POPUP_ITEM_KEY)); | ||
| return popup; | ||
| }); |
Copilot
AI
Jan 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getPopup method stores the current GameListItem in the ListView's properties, but this state is only cleared when the popup is hidden. If the popup is shown again before being hidden, or if the reference changes, there could be issues with stale item references. Consider also clearing the item reference in preparePopupMenu or ensuring proper cleanup in all code paths.
No description provided.