Eclipse插件开发:如何在Eclipse编辑器中监听事件

时间:2014-11-11 18:34:22

标签: eclipse events eclipse-plugin eclipse-pde eclipse-jdt

我正在尝试开发一个eclipse插件。我知道这件事的基础知识。

在示例插件模板中,当我们在eclipse的测试实例中单击菜单项(或在这种情况下在下图中带有eclipse图标的按钮)时,执行 sampleHandler.java <的方法/ strong>已执行,并出现如下图所示的弹出窗口。

enter image description here

每当我在代码编辑器中按某个键(让我们说退格键)而不是单击任何菜单项(或按钮)时,我想调用'execute'方法。

SampleHandler.java

   
 public class SampleHandler extends AbstractHandler {

    public SampleHandler() {
    }

    /**
     * the command has been executed, so extract extract the needed information
     * from the application context.
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {
        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
        MessageDialog.openInformation(
                window.getShell(),
                "Sdfsdfsadf",
                "Hello, Eclipse world");
        return null;
    }
   }

我尝试了other posts中给出的建议,但我无法实现所需的功能。

根据我在上面的参考文章中的理解,我尝试了下面的代码 -

    package eventlisten.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;


import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;

/**
 * Our sample handler extends AbstractHandler, an IHandler base class.
 * @see org.eclipse.core.commands.IHandler
 * @see org.eclipse.core.commands.AbstractHandler
 */
public class SampleHandler extends AbstractHandler {
    /**
     * The constructor.
     */
    public SampleHandler() {
    }

    /**
     * the command has been executed, so extract extract the needed information
     * from the application context.
     */
    public Object execute(ExecutionEvent event) throws ExecutionException {

        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
        MessageDialog.openInformation(window.getShell(),"EventListen","Trying event listen");
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        IEditorPart editor = page.getActiveEditor();
        IEditorInput input = editor.getEditorInput();  
        IDocument document=(((ITextEditor)editor).getDocumentProvider()).getDocument(IDocument.class);

        document.addDocumentListener(new IDocumentListener() //**this is line 45**
        {
            @Override
            public void documentAboutToBeChanged(DocumentEvent event) {
                // TODO Auto-generated method stub
                System.out.println("Hello");
            }

            @Override
            public void documentChanged(DocumentEvent event) {
                // TODO Auto-generated method stub
                System.out.println("Hello second");

            }
        });

        return null;
    }
}

但是在显示弹出窗口后,它会抛出异常 -

java.lang.NullPointerException
at eventlisten.handlers.SampleHandler.execute(SampleHandler.java:45)
at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:290)
at org.eclipse.core.commands.Command.executeWithChecks(Command.java:499)
at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
at org.eclipse.ui.menus.CommandContributionItem.handleWidgetSelection(CommandContributionItem.java:829)
at org.eclipse.ui.menus.CommandContributionItem.access$19(CommandContributionItem.java:815)
at org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(CommandContributionItem.java:805)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1276)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3562)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3186)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2701)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2665)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2499)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:679)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:668)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
at org.eclipse.equinox.launcher.Main.main(Main.java:1414)

有人可以指导我完成整个过程吗?如果需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:3)

您的第一个问题似乎是当用户按下按钮时您只与文档交互。有更好的方法来设置它。
据我所知,您想要检测用户何时修改文档(可能通过键入),在任何地方键入任何键,或者修改代码的AST。您可能只会找到以下有用或相关的一个解决方案。

聆听文件更改

您尝试的解决方案最接近第一个解决方案,因此我将从那里开始。我做了这样的事情(在你链接的帖子中,事实证明)。首先让你的插件扩展org.eclipse.ui.startup扩展点,并定义一个类来覆盖IStartup

earlyStartup()看起来像是:

@Override
public void earlyStartup() {
    IWorkbench wb = PlatformUI.getWorkbench();
    wb.addWindowListener(generateWindowListener());
}

我们会听窗户打开,当他们这样做时,

private IWindowListener generateWindowListener() 
{
    return new IWindowListener() {
        @Override
        public void windowOpened(IWorkbenchWindow window) {
            IWorkbenchPage activePage = window.getActivePage(); 
            activePage.addPartListener(generateIPartListener2());
        }

        @Override
        public void windowDeactivated(IWorkbenchWindow window) {}

        @Override
        public void windowClosed(IWorkbenchWindow window) {}

        @Override
        public void windowActivated(IWorkbenchWindow window) {}
    };
}

此部分监听器是您应该获取EditorPart的地方,这意味着您可以添加文档监听器:

private IPartListener2 generateIPartListener2() 
{
    return new IPartListener2() {

        private void checkPart(IWorkbenchPartReference partRef) {
        IWorkbenchPart part = partRef.getPart(false);
            if (part instanceof IEditorPart)
            {
                IEditorPart editor = (IEditorPart) part;
                IEditorInput input = editor.getEditorInput();
                if (editor instanceof ITextEditor && input instanceof FileEditorInput)  //double check.  Error Editors can also bring up this call
                {
                    IDocument document=(((ITextEditor)editor).getDocumentProvider()).getDocument(input);
                    document.addDocumentListener(/* your listener from above*/);
                }
            }
        }

        @Override
        public void partOpened(IWorkbenchPartReference partRef) {
            checkPart(partRef);
        }

        @Override
        public void partInputChanged(IWorkbenchPartReference partRef) 
        {
            checkPart(partRef);
        }           

        @Override
        public void partVisible(IWorkbenchPartReference partRef){}

        @Override
        public void partHidden(IWorkbenchPartReference partRef) {}

        @Override
        public void partDeactivated(IWorkbenchPartReference partRef)  {}

        @Override
        public void partClosed(IWorkbenchPartReference partRef) {}

        @Override
        public void partBroughtToTop(IWorkbenchPartReference partRef) {}

        @Override
        public void partActivated(IWorkbenchPartReference partRef) {}
    };
}

只听取keypressess

这最终会更容易实现,但可能会非常嘈杂。我们正在查看DisplayListener,它们会直接进入SWT事件循环。

您希望再次执行earlyStartup()扩展,并具有以下内容:

@Override
public void earlyStartup() {
    Display display = Display.getDefault();
    display.setFilter(SWT.KeyUp, new Listener() {
        @Override
        public void handleEvent(Event event) {
            //do stuff here.  Be careful, this may cause lag
        }
     });
}

听Java AST更改 最后一个具有原始keyup方法的简单性,但可能与我建议的第一个一样在语义上有用。我们将直接收听JavaCore

再次,在earlyStartup方法()

 JavaCore.addElementChangedListener(new IElementChangedListener() {

        @Override
        public void elementChanged(ElementChangedEvent event)
        {
            //do stuff with the event
        }
    });

结论:幸运的是,这三种方法中的一种对您有用。我有理由在我的Eclipse开发职业中使用每一个 - 每个都以自己的方式有用。

我希望这会有所帮助。