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

如何为XML生成的Eclipse菜单添加MenuListener监听焦点事件

How to Add a MenuListener to an XML-Configured Eclipse Menu for Focus Events (Before Click)

Question

I've defined a menu in my Eclipse plug-in using the org.eclipse.ui.editorActions extension point, as shown below. How can I add a MenuListener to this menu so that I can run code when the menu receives focus (before it's clicked)?

<extension point="org.eclipse.ui.editorActions">
  <editorContribution targetID="net.sourceforge.texlipse.TexEditor" id="net.sourceforge.texlipse.editor.editorContribution">
    <menu label="&amp;TTS Settings" id="net.sourceforge.texlipse.menus.tts">
      <separator name="sourceGroup"/>
      <separator name="latexGroup"/>
      <separator name="commentGroup"/>
      <separator name="spellGroup"/>
    </menu>
    <action class="net.sourceforge.texlipse.actions.TTSPdfModeAction" icon="icons/start.png" id="net.sourceforge.texlipse.actions.TTSPdfModeAction" definitionId="net.sourceforge.texlipse.commands.PDF" label="&amp;PDF" menubarPath="net.sourceforge.texlipse.menus.tts/sourceGroup" style="push" toolbarPath="latexGroup" tooltip="PDF"/>
    <action class="net.sourceforge.texlipse.actions.TTSStopAction" icon="icons/stop.png" id="net.sourceforge.texlipse.actions.TTSStopAction" definitionId="net.sourceforge.texlipse.commands.TTSStop" label="&amp;Stop" menubarPath="net.sourceforge.texlipse.menus.tts/sourceGroup" style="push" toolbarPath="latexGroup" tooltip="Stop"/>
  </editorContribution>
</extension>

Answer

Great question! Eclipse's plugin.xml doesn't support directly configuring MenuListeners for menus defined via extensions. Instead, you'll need to dynamically fetch the menu instance through code and attach the listener at the right time. Here's how to implement this:

1. Choose the Right Timing to Attach the Listener

The most reliable approach is to listen for when your target editor (TexEditor) is activated. This ensures you hook into the menu as soon as the editor is ready to use. We'll use an IPartListener2 to handle this event.

2. Retrieve the Menu Manager and Add the Listener

First, create a part listener class to handle editor activation and attach your menu listener:

import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.part.IPartListener2;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IActionBars;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.jface.action.IMenuListener;

public class TexEditorMenuListener implements IPartListener2 {

    @Override
    public void partActivated(IWorkbenchPartReference partRef) {
        IWorkbenchPart part = partRef.getPart(true);
        // Check if the activated part is your TexEditor
        if (part instanceof net.sourceforge.texlipse.TexEditor) {
            IEditorPart editor = (IEditorPart) part;
            IActionBars actionBars = editor.getEditorSite().getActionBars();
            
            // Get the main menu manager and find your TTS Settings menu by ID
            MenuManager mainMenu = (MenuManager) actionBars.getMenuManager();
            IMenuManager ttsMenu = mainMenu.findMenuUsingPath("net.sourceforge.texlipse.menus.tts");
            
            if (ttsMenu != null) {
                // Add a MenuListener to trigger when the menu is about to show (focused but not clicked)
                ttsMenu.addMenuListener(new IMenuListener() {
                    @Override
                    public void menuAboutToShow(IMenuManager manager) {
                        // This runs when the menu receives focus (mouse hover or keyboard navigation)
                        System.out.println("TTS Settings menu focused - running pre-click logic");
                        // Add your custom operations here (e.g., update menu state, load data)
                    }
                });

                // Optional: Listen for focus on individual menu items
                // Note: The Menu control is only created after the menu is first opened
                ttsMenu.addMenuListener(new IMenuListener() {
                    @Override
                    public void menuAboutToShow(IMenuManager manager) {
                        Menu menu = ((MenuManager) manager).getMenu();
                        if (menu != null) {
                            for (int i = 0; i < menu.getItemCount(); i++) {
                                MenuItem item = menu.getItem(i);
                                item.addFocusListener(new FocusAdapter() {
                                    @Override
                                    public void focusGained(FocusEvent e) {
                                        // Trigger when a specific menu item gains focus
                                        System.out.println("Menu item focused: " + item.getText());
                                        // Add your item-specific logic here
                                    }
                                });
                            }
                        }
                    }
                });
            }
        }
    }

    // Implement other IPartListener2 methods with empty bodies (or add logic if needed)
    @Override public void partBroughtToTop(IWorkbenchPartReference partRef) {}
    @Override public void partClosed(IWorkbenchPartReference partRef) {}
    @Override public void partDeactivated(IWorkbenchPartReference partRef) {}
    @Override public void partHidden(IWorkbenchPartReference partRef) {}
    @Override public void partOpened(IWorkbenchPartReference partRef) {}
    @Override public void partVisible(IWorkbenchPartReference partRef) {}
    @Override public void partInputChanged(IWorkbenchPartReference partRef) {}
}

3. Register the Part Listener in Your Plugin Activator

Add this listener to your plugin's activator class so it runs when the plugin starts:

import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

public class Activator extends AbstractUIPlugin {
    private static Activator plugin;

    @Override
    public void start(BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
        
        // Register the part listener to monitor editor activation
        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().addPartListener(new TexEditorMenuListener());
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        plugin = null;
        super.stop(context);
    }

    public static Activator getDefault() {
        return plugin;
    }
}

Key Notes

  • Menu vs. Menu Item Focus: The menuAboutToShow method triggers when the menu itself receives focus (e.g., mouse hover, keyboard navigation to the menu). If you need to track focus on individual menu items, use the FocusListener approach shown above (remember the Menu control only exists after the menu is first opened).
  • Avoid Duplicate Listeners: If you want to prevent adding the listener multiple times when the editor is activated repeatedly, add a check to see if the listener is already attached before adding it.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:50:30