3

在 RCP 应用程序中,如何以编程方式定义和打开新窗口?我想打开几个窗口 - 每个窗口显示不同的数据。如何为每个窗口设置不同的输入?

我想模拟 Eclipse IDE 的相同功能(窗口 --> 新窗口),但我希望每个新打开的窗口都有不同的输入。我正在尝试使用: IWorkbenchPage newPage = window.openPage(inputObject); 如何以编程方式定义标识窗口中显示的数据的“inputObject”?

4

6 回答 6

4

Eclipse 术语中的工作台窗口是一个通常包含菜单、工具栏、编辑器区域和视图的窗口。Eclipse RCP 应用程序通常包含一个窗口,但有些应用程序允许创建多个窗口。例如,在 Eclipse IDE 中,可以通过从窗口菜单中选择“新窗口”来打开另一个窗口。透视图可以独立设置到每个窗口中。

尽管多个窗口可能会令人困惑,但它们也非常有用。例如,如果用户可能在两个不同的数据源上工作,但针对每个数据源打开了多个编辑器和视图,那么打开两个窗口会很有用。通过打开 RCP 应用程序的两个实例可以实现相同的效果。但是,这需要加载多个代码副本和其他资源,需要为每个数据源对应用程序进行完全初始化,并且会使窗口之间的交叉通信更加困难。

要允许 RCP 应用程序的用户打开另一个窗口,您有两个选择。

您可以在 RCP 应用程序中包含“新窗口”菜单项。这可以通过将工作台提供的操作添加到您的 RCP 应用程序来完成。修改您的 ActionBarAdvisor 类:

添加到字段声明:

private IWorkbenchAction newWindowAction;

添加到您进行操作的代码中(通常是一个名为 makeActions 的方法):

newWindowAction = ActionFactory.OPEN_NEW_WINDOW.create(window);
register(newWindowAction);

添加到创建菜单的代码中:

menu.add(newWindowAction);

其中 menu 通常是 Window 菜单。如果您的应用程序中还没有 Window 菜单并且想要创建一个,则以下行将起作用:

MenuManager menu = new MenuManager("&Window", IWorkbenchActionConstants.M_WINDOW);

这将为您提供一个菜单项,该菜单项将以与 Eclipse IDE 中的 Window->New Window 菜单项相同的方式创建一个新窗口。

但是,这无法控制输入。第二个窗口可能打开了一组不同的视图和编辑器,并且可能有不同的透视图集,但它仍然具有相同的“输入”。例如,在 Eclipse IDE 中,您可以打开第二个窗口,但如果您切换工作区,那么这将适用于所有窗口。

创建新窗口的第二种方法是通过创建页面以编程方式进行。这允许您为窗口设置“输入”。因此,在一个窗口中打开视图可能会导致显示与在另一个窗口中打开相同视图不同的数据。

从技术上讲,窗口没有输入。页面有输入。一个窗口最多可以包含一页。从某些方法名称看来,一个窗口可以有多个页面(例如 getActivePage 暗示有非活动页面)。这些方法名称是 Eclipse 2.0 支持多个页面时的保留。

以编程方式打开新页面:

        IWorkbenchPage newPage = window.openPage(myInput);

如果窗口尚未包含页面,此方法将在给定窗口中创建一个新页面,否则将创建一个新窗口来包含该页面。

如果您支持具有不同输入的多个窗口,那么您应该在每个窗口中设置一个标题来区分每个窗口:

        newPage.getWorkbenchWindow().getShell().setText("My App - " + myInput.getName());

在某些情况下,您可能希望将输入更改为窗口。您无法更改页面的输入,因此您必须通过关闭现有页面并创建新页面来执行此操作。以下代码将关闭现有页面:

        IWorkbenchPage activePage = window.getActivePage();
        activePage.close();

请注意,Eclipse 提供的某些视图使用页面输入。例如,Common Navigator 视图将使用页面输入作为导航树的根元素。

要从您自己的视图访问页面输入,您可以调用site.getPage().getInput(). 如果您没有要开始的站点上下文,则调用以下命令将为您获取输入:

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getInput();

请注意,“输入”是一个对象。它可以是您喜欢的任何类的对象。当您从 中取回它时Page::getInput(),将其转换回适当的类。您通常不应该创建一个新类作为输入。您几乎总是可以使用现有的类。这通常是对象模型的顶级对象。Eclipse 框架对此输入不做任何事情,除了存储它并在Page::getInput()调用时将其传回。

于 2009-05-20T23:19:11.913 回答
2

您需要了解如何在 Eclipse 插件模型中实现视图。这可以通过添加扩展点和配置属性或通过代码来实现。配置属性是首选方法。两者都在以下位置进行了解释:

http://www.vogella.de/articles/RichClientPlatform/article.html#views

该站点有很多关于 Eclipse 开发的好文章:

http://www.vogella.de/eclipse.html

无论如何,正如 PSU_Kardi 建议的那样,通读整篇文章是个好主意。

于 2009-05-14T20:08:39.930 回答
1

我认为您需要更好地为我或其他人定义一个“窗口”来回答这个问题。

您是否正在创建一个想要多次打开的插件,在这种情况下,您可能需要一个编辑器并且需要确保您没有使用单例模式——您可以在清单文件中指定该模式。

或者您是否正在尝试创建一个要显示数据的窗口?喜欢视图?如果您这样做,您将需要阅读有关如何创建 ViewPart 并确保正确扩展所有内容。

我可以建议去我最喜欢的两个 RCP 站点吗

http://www.vogella.de/articles/RichClientPlatform/article.html

http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/CatalogSWT-JFace-Eclipse.htm

于 2009-05-14T16:10:57.427 回答
1

你应该确保你真的想打开一堆其他的窗口。也许您可以通过在现有窗口中打开一些新视图或编辑器来实现相同的目的?使用多个视图通常更容易让用户理解,因为它们没有呈现几个看起来几乎相同的窗口。它还使您更容易显示视图之间的关系。

话虽如此,您可以调用IWorkbench.openWorkbenchWindow创建一个全新的窗口。一个很好的例子是 Window --> New Window 的代码,它位于OpenNewWindowMenu中。

于 2009-05-15T17:30:02.113 回答
1

以下处理程序 - 每次调用其 @Execute 方法时 - 创建一个新的 TrimmedWindow ,其数据内容彼此独立:

package com.vogella.tasks.ui.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.basic.impl.TrimmedWindowImpl;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;

import com.vogella.tasks.ui.parts.DynamicPart;

public class OpenAdditionalWindowHandler {
    private static final String PART_DESCRIPTOR_ID = "com.vogella.tasks.ui.partdescriptor.static.part";
    static int posX = 20;
    static int posY = 20;
    static int counter = 0;

    /**
     * Opens a new TrimmedWindow based on the (template) definition. Each time invoked a separate window is opened with independent data content.
     */
    @Execute
    public void execute(EPartService partService, MWindow window, MApplication application, EModelService modelService) throws WorkbenchException {

        // Get the predefined TrimmedWindow and clone it
        MUIElement element = modelService.find("com.vogella.tasks.ui.trimmedwindow.zusatz", application);
        TrimmedWindowImpl clonedWindow = (TrimmedWindowImpl) modelService.cloneElement(element, application);
        application.getChildren().add(clonedWindow);
        modelService.bringToTop(clonedWindow);
        clonedWindow.setToBeRendered(true);

        // Shift the new windows a little bit each time a new one is created
        shiftWindowPositionSoTheyDontExactlyOverlay(clonedWindow);

        // Derive new Part Descriptor Id with counter & create new part
        final String dynamicallyCreatedPartId = PART_DESCRIPTOR_ID + counter++;
        MPart dynamicallyCreatedPart = partService.createPart(PART_DESCRIPTOR_ID);

        if (dynamicallyCreatedPart != null) {
            // Add the part to the newly cloned trimmed window
            clonedWindow.getChildren().add(dynamicallyCreatedPart);

            dynamicallyCreatedPart.setElementId(dynamicallyCreatedPartId);
            dynamicallyCreatedPart.setLabel("My part nbr " + counter);

            final DynamicPart staticPseudoAspect = (DynamicPart) dynamicallyCreatedPart.getObject();
            staticPseudoAspect.setContent("Dynamic part content nbr " + counter);
            clonedWindow.getChildren().get(0).setVisible(true);
            clonedWindow.getChildren().get(0).setToBeRendered(true);

        }

    }

    private void shiftWindowPositionSoTheyDontExactlyOverlay(TrimmedWindowImpl clonedWindow) {
        posX = posX + 20;
        posY = posY + 20;
        clonedWindow.setX(posX);
        clonedWindow.setY(posY);
    }

}

Trimmed 窗口在应用程序模型中定义为模板。与应用模型中以 PartDescriptor 形式描述的 Part 相同。

在此处输入图像描述

于 2020-07-24T17:56:36.290 回答
0

这会在主应用程序窗口旁边打开一个新窗口:

package any.pack;

import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.basic.impl.PartImpl;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.swt.SWT;

public class WindowOpener {

    private MWindow createWindow(EModelService modelService, MApplication application) {
        MWindow window = modelService.createModelElement(MTrimmedWindow.class);
        window.setElementId("com.ubs.cqe.ui.window.aside.1");
        window.setLabel("Second Window");
        window.getPersistedState().put(IPresentationEngine.STYLE_OVERRIDE_KEY, "" + SWT.SHELL_TRIM);
        window.setVisible(true);
        window.setX(20);
        window.setY(20);
        window.setWidget(700);
        window.setHeight(500);
        application.getChildren().add(window); // Add window to application
        return window;
    }
    
}
于 2020-07-24T18:02:21.393 回答