Eclipse插件开发:如何在Eclipse编辑器中监听事件 [英] Eclipse plugin development : How to listen events in Eclipse editor

查看:2798
本文介绍了Eclipse插件开发:如何在Eclipse编辑器中监听事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在一个示例插件模板中,当我们点击菜单条目(或在这种情况下点击下面的图像中的eclipse图标)执行eclipse的测试实例执行 sampleHandler.java 方法,并显示如下图所示的弹出窗口。





我想在代码编辑器中按某些键(允许说退格键)而不是单击任何菜单项(或按钮)时,调用执行方法。



SampleHandler.java

  public class SampleHandler extends AbstractHandler {

public SampleHandler(){
}

/ **
*命令已执行,因此从应用程序上下文中提取所需的信息
*。
* /
public Object execute(ExecutionEvent event)throws ExecutionException {
IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event);
MessageDialog.openInformation(
window.getShell(),
Sdfsdfsadf,
Hello,Eclipse world);
返回null;
}
}

我尝试了在其他帖子,但我无法实现所需的功能。



根据上述引用文章的理解,我尝试下面的代码 -

  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;

/ **
*我们的示例处理程序扩展了一个IHandler基类的AbstractHandler。
* @see org.eclipse.core.commands.IHandler
* @see org.eclipse.core.commands.AbstractHandler
* /
public class SampleHandler extends AbstractHandler {
/ **
*构造函数。
* /
public SampleHandler(){
}

/ **
*命令已执行,因此提取所需信息
*从应用程序上下文。
* /
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)编辑器).getDocumentProvider())。getDocument(IDocument.class);

document.addDocumentListener(new IDocumentListener()// ** this is line 45 **
{
@Override
public void documentAboutToBeChanged(DocumentEvent event){
// TODO自动生成的方法stub
System.out.println(Hello);
}

@Override
public void documentChanged(DocumentEvent事件){
// TODO自动生成的方法存根
System.out.println(Hello second);

}
});

返回null;
}
}

但显示弹出窗口后,它会抛出例外 -

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

有人可以指导我完成这个过程吗?让我知道如果需要更多的信息。

解决方案

你的第一个问题似乎是当用户按下按钮时,您只能与文档进行交互。有更好的方法来设置它。

据我所知,您想要检测用户何时修改文档(可能通过键入),任何键都可以在任何地方键入,或者当<代码的一个href =http://en.wikipedia.org/wiki/Abstract_syntax_tree =nofollow> AST 被修改。您可能只会找到 以下有用或相关的解决方案。



聆听文档更改



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



earlyStartup()将看起来像:

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

我们会听窗口打开,当他们这样做时, p>

  private IWindowListener generateWindowListener()
{
返回新的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()
{
返回新的IPartListener2(){

private void checkPart(IWorkbenchPartReference partRef){
IWorkbenchPart part = partRef.getPart(false);
if(part instanceof IEditorPart)
{
IEditorPart editor =(IEditorPart)part;
IEditorInput input = editor.getEditorInput();
if(编辑器instanceof的ITextEditor&&输入instanceof FileEditorInput)//双重检查。错误编辑器也可以调用此调用
{
IDocument document =(((ITextEditor)编辑器).getDocumentProvider())。getDocument(input);
document.addDocumentListener(/ *你的监听器从上面* /);
}
}
}

@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){}
};
}

只听紧呼



最终实现起来更简单,但可能非常嘈杂。我们将看看显示听众,它们进入SWT事件循环。



你会想要再次执行earlyStartup()扩展,并具有以下内容:

  @Override 
public void earlyStartup(){
显示display = Display.getDefault();
display.setFilter(SWT.KeyUp,new Listener(){
@Override
public void handleEvent(Event event){
// do stuff here。请小心,这可能导致滞后
}
});
}

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



再次,在earlyStartup方法()



< pre class =lang-java prettyprint-override> JavaCore.addElementChangedListener(new IElementChangedListener(){

@Override
public void elementChanged(ElementChangedEvent event)
{
//做事情
}
});

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



我希望这有助于。


I am trying to develop an eclipse plug-in. I am aware about the basics of this thing.

In a sample plugin template when we click the menu entry (or button with eclipse icon in below image in this case) in testing instance of eclipse, execute method of sampleHandler.java is executed and a pop-up shown in image below appears.

I want to invoke 'execute' method whenever I press some key (lets say backspace) in code editor instead of clicking any menu entry (or button).

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;
    }
   }

I tried suggestions given in other posts but I am unable to achieve the desired functionality.

As per my understanding from referenced post in above line, I tried below code -

    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;
    }
}

But after showing the pop-up , it throws the exception -

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)

Can someone guide me through the process? Let me know in case more information is required.

解决方案

Your first problem seems to be that you only interact with the documents when the user presses the button. There are better ways to set this up.
As far as I can tell, you want to either detect when a user modifies a document (probably by typing), any key is typed anywhere, or when the AST of the code is modified. You will probably only find one of the solutions below useful or relevant.

Listening to Document Changes

The solution you attempted is closest to the first one, so I'll start there. I did something like this (in the post you linked, as it turns out). Start by making your plugin extend the org.eclipse.ui.startup extension point, and define a class to override IStartup

That earlyStartup() will look something like:

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

We'll listen for windows to open, and when they do,

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) {}
    };
}

This part listener is where you should get the EditorPart, which means you can add the document listener:

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) {}
    };
}

Listening to just the keypressess

This ends up being simpler to implement, but may be very noisy. We'll be looking at the Display and the Listener, which gets right into the SWT event loop.

You'll want to do the earlyStartup() extension again, and have something like:

@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
        }
     });
}

Listening to Java AST changes The final one has the simplicity of the raw keyup approach, but will probably be as semantically useful as the first one I suggested. We will be listening to the JavaCore directly.

Again, in the earlyStartup method()

 JavaCore.addElementChangedListener(new IElementChangedListener() {

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

Conclusion: With luck, one of these three methods is useful to you. I've had reason to use each in my Eclipse development career -- each is useful in its own way.

I hope this helps.

这篇关于Eclipse插件开发:如何在Eclipse编辑器中监听事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆