You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX ContextMenu运行时元素变更不显示问题求助

Fixing ContextMenu Updates in Your AutosuggestMenu

It sounds like you’re hitting exactly the issue you suspected: by default, JavaFX’s ObservableList only notifies listeners when the list’s structure changes (like adding/removing items) — not when the properties of individual items in the list are modified. That’s why your ContextMenu isn’t updating even when you tweak the suggestions inside the list.

The fix here is to use an extractor when creating your ObservableList. Extractors tell the list to monitor specific properties of each item, so any changes to those properties will trigger list change events, which the ContextMenu will pick up and reflect visually.

Step 1: Define a Suggestion Object (If Not Already Using One)

If you’re working with raw strings, wrapping them in a simple object with observable properties makes tracking changes way easier. Here’s a basic implementation:

public class Suggestion {
    private final StringProperty text = new SimpleStringProperty();

    public Suggestion(String initialText) {
        this.text.set(initialText);
    }

    // Standard property getters/setters
    public String getText() { return text.get(); }
    public void setText(String newText) { this.text.set(newText); }
    public StringProperty textProperty() { return text; }
}

Step 2: Create the ObservableList with an Extractor

When initializing your suggestions list, pass an extractor that returns the observable properties you want to monitor. For our Suggestion class, that’s the textProperty():

ObservableList<Suggestion> suggestions = FXCollections.observableArrayList(
    suggestion -> new Observable[] { suggestion.textProperty() }
);

If you’re using MenuItem directly instead of a custom class, you can still use an extractor to monitor the MenuItem’s textProperty():

ObservableList<MenuItem> menuItems = FXCollections.observableArrayList(
    menuItem -> new Observable[] { menuItem.textProperty() }
);

Step 3: Update Suggestions Without Replacing the List

Now, when your TextField’s listener finds matching suggestions, you can modify existing items in the list instead of clearing and re-adding them. The extractor will ensure those changes trigger updates in the ContextMenu.

Here’s how your TextField listener might look:

textField.textProperty().addListener((observable, oldText, newText) -> {
    // Get your matching suggestions from your word collection
    List<String> matchingWords = findMatchingWords(newText);

    // Update existing suggestions to match the new matches
    int matchCount = matchingWords.size();
    int currentSize = suggestions.size();

    // Update existing items first
    for (int i = 0; i < Math.min(matchCount, currentSize); i++) {
        suggestions.get(i).setText(matchingWords.get(i));
    }

    // Add new items if there are more matches than current items
    if (matchCount > currentSize) {
        for (int i = currentSize; i < matchCount; i++) {
            suggestions.add(new Suggestion(matchingWords.get(i)));
        }
    }
    // Remove extra items if there are fewer matches than current items
    else if (matchCount < currentSize) {
        while (suggestions.size() > matchCount) {
            suggestions.remove(suggestions.size() - 1);
        }
    }
});

Step 4: Connect the List to Your ContextMenu

Finally, bind your ContextMenu’s items to the suggestions list. If using the custom Suggestion class, map each Suggestion to a MenuItem (with a binding to keep the text in sync):

// Create a mapped list of MenuItems from your Suggestions
ObservableList<MenuItem> contextMenuItems = FXCollections.observableArrayList();
Bindings.bindContent(contextMenuItems, suggestions,
    suggestion -> {
        MenuItem item = new MenuItem();
        item.textProperty().bind(suggestion.textProperty());
        // Add action to insert the suggestion into the TextField
        item.setOnAction(event -> textField.setText(suggestion.getText()));
        return item;
    },
    (menuItem, suggestion) -> {} // Optional cleanup logic if needed
);

// Set the ContextMenu's items
ContextMenu autoSuggestMenu = new ContextMenu();
autoSuggestMenu.setItems(contextMenuItems);
textField.setContextMenu(autoSuggestMenu);

This setup ensures that whenever you update the text of a Suggestion in your list, the corresponding MenuItem in the ContextMenu will automatically update its text — no need to rebuild the entire list every time the input changes.

内容的提问来源于stack exchange,提问作者SKNB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:54:42