【问题标题】:Eclipse RCP application - Create a window programmaticallyEclipse RCP 应用程序 - 以编程方式创建窗口
【发布时间】:2010-10-26 05:45:50
【问题描述】:

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

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

【问题讨论】:

    标签: eclipse eclipse-rcp rcp


    【解决方案1】:

    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 菜单 = 新的 MenuManager( “&窗户”, 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() 时将其传回。

    【讨论】:

    • 看起来这是 RCP3。
    【解决方案2】:

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

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

    那个网站有很多关于 Eclipse 开发的好文章:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

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

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

      【讨论】:

      • 根本不回答这个问题。 1. 工作台窗口在 Eclipse RCP 架构中定义良好。问题的提交者熟悉 Eclipse 窗口,并且应该合理地期望任何提供答案的人也会熟悉它们。 2. 您提供了两篇文章的链接,但它们都没有以任何方式涵盖多窗口的主题。第二篇文章仅关于 SWT 和 JFace 问题,因此与该问题无关。 poser为什么要提供两个链接,第一个
      • 我完全同意@user85259
      【解决方案4】:

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

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

      【讨论】:

      • OpenNewWindowMenu 链接已弃用,请提供新链接@AndrewEidsness
      【解决方案5】:

      以下 Handler - 每次调用其 @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);
          }
      
      }
      

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

      enter image description here

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-13
          • 2018-05-23
          • 2013-03-19
          • 2014-12-21
          • 2013-03-02
          相关资源
          最近更新 更多