【问题标题】:Eclipse RCP application - custom splash screenEclipse RCP 应用程序 - 自定义启动画面
【发布时间】:2011-12-01 17:51:46
【问题描述】:

我目前正在开发一个 Eclipse RCP 应用程序,我在其中尝试实现一个自定义启动屏幕处理程序,带有一个进度条(行为类似于您可以在 .product 定义中定义的默认进度条)和多个循环背景图片。

以这种方式编辑主应用程序插件的扩展后:

[...]
<!-- install custom splash handler -->
<extension point="org.eclipse.ui.splashHandlers">
   <splashHandler
        class="com.example.application.splash.SlideShowSplashHandler"
        id="splash.slideshow">
   </splashHandler>
   <splashHandlerProductBinding
        productId="com.example.application.product"
        splashId="com.example.application.splash.slideshow">
   </splashHandlerProductBinding>
</extension>
<!-- define images (in plugin root directory) to be shown -->
<extension point="com.example.application.splashExtension">
     <splashExtension id="01" image="01_Splash2Ag.bmp"></splashExtension>
     <splashExtension id="02" image="02_Splash3Ag.bmp"></splashExtension>
     <splashExtension id="00" image="00_Splash1Ag.bmp"></splashExtension>         
</extension>
[...]

我正在尝试实现自定义闪屏处理程序类:

public class SlideShowSplashHandler extends AbstractSplashHandler {

    private List<Image> fImageList;
    private ProgressBar fBar;
    private final static String F_SPLASH_EXTENSION_ID = "com.example.application.splashExtension"; //NON-NLS-1
    private final static String F_ELEMENT_IMAGE = "image"; //NON-NLS-1
    private int imageIdx = 0;

    public SlideShowSplashHandler() {
        fImageList = new ArrayList<Image>(5);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
     */
    public void init(Shell splash) {
        // Store the shell
        super.init(splash);
            // Force shell to inherit the splash background
            getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT); 
        // Load all splash extensions
        loadSplashExtensions();
        // If no splash extensions were loaded abort the splash handler
        if (hasSplashExtensions() == false) return;
        // Create UI
        createUI(splash);
    }

    private boolean hasSplashExtensions() {
        if (fImageList.isEmpty()) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public IProgressMonitor getBundleProgressMonitor() {
       return new NullProgressMonitor() {

          @Override
          public void beginTask(String name, final int totalWork) {
            getSplash().getDisplay().syncExec(new Runnable() {
              public void run() {
                  fBar.setSelection(50);
              }
            });
          }

          @Override
          public void subTask(String name) {
            getSplash().getDisplay().syncExec(new Runnable() {
              public void run() {
                  if (fBar.getSelection() < 100) fBar.setSelection(fBar.getSelection() + 10);
                  if (imageIdx >= fImageList.size()) imageIdx = 0;
                  Image image = fImageList.get(imageIdx++);
                  getSplash().setBackgroundImage(image);
                  getSplash().setRedraw(true);
                  getSplash().redraw();
              }
            });
          }
        };
    }

    private void createUI(Shell shell) {

        Composite container = new Composite(shell, SWT.NONE);
        container.setLayout(new GridLayout(1, false));
        container.setLocation(5, 374);
        container.setSize(480, 15);

        /* Progress Bar */
        fBar = new ProgressBar(container, SWT.HORIZONTAL);
        fBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
        ((GridData) fBar.getLayoutData()).heightHint = 13;
        fBar.setMaximum(100);
        fBar.setSelection(25);

        /* Version Label */
        Label versionLabel = new Label(container, SWT.NONE);
        versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
        //versionLabel.setFont(fVersionFont);
        //versionLabel.setForeground(fVersionColor);
        //versionLabel.setText(NLS.bind(Messages.SplashHandler_BUILD, "2.1 Nightly")); //$NON-NLS-1$

        /* Layout All */
        shell.layout(true, true);
    }   

    private void loadSplashExtensions() {
        // Get all splash handler extensions
        IExtension[] extensions = Platform.getExtensionRegistry()
                .getExtensionPoint(F_SPLASH_EXTENSION_ID).getExtensions();
        // Process all splash handler extensions
        for (int i = 0; i < extensions.length; i++) {
            processSplashExtension(extensions[i]);
        }
    }

    /**
     * Parse the extension points with the images filename.
     */
    private void processSplashExtension(IExtension extension) {
        // Get all splash handler configuration elements
        IConfigurationElement[] elements = extension.getConfigurationElements();
        // Process all splash handler configuration elements
        for (int j = 0; j < elements.length; j++) {
            processSplashElements(elements[j]);
        }
    }

    /**
     * Create the images defined as extension points
     */
    private void processSplashElements(IConfigurationElement configurationElement) {

        String name = configurationElement.getAttribute(F_ELEMENT_IMAGE);
        ImageDescriptor descriptor = Activator.getImageDescriptor("/"+name);
        if (descriptor != null) {
            Image image = descriptor.createImage();
            if (image !=null) {
                fImageList.add(image);
            }
        }
    }

    public void dispose() {
        super.dispose();
        // Check to see if any images were defined
        if ((fImageList == null) ||
                fImageList.isEmpty()) {
            return;
        }
        // Dispose of all the images
        Iterator<Image> iterator = fImageList.iterator();
        while (iterator.hasNext()) {
            Image image = iterator.next();
            image.dispose();
        }
    }
}

问题是进度条正常工作,而没有显示图像。在调试时,我可以验证图像是否真的被找到并加载,并在 shell 中正确设置;外壳似乎没有被重绘。我错过了什么吗?=

【问题讨论】:

    标签: java eclipse eclipse-rcp splash-screen


    【解决方案1】:

    我可以在 linux 和 windows 上解决这个问题,但它在 macos/cocoa 上不起作用(在每个图像幻灯片迭代中,初始屏幕看起来都“乱码”)。

    确实非常简单,只需在启动外壳和包含小部件的容器之间附加一个额外的 Composite;然后更改新创建的容器对象上的背景图像。

    private void createUI(Shell shell) {
        Composite bgcontainer = new Composite(shell, SWT.NONE); // new
        [...]
        Composite container = new Composite(bgcontainer, SWT.NONE);
        [...]
        fBar = new ProgressBar(container, SWT.HORIZONTAL);
        [...]
        Label versionLabel = new Label(container, SWT.NONE);
        versionLabel.setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));
        shell.layout(true, true);
    }   
    
    @Override public IProgressMonitor getBundleProgressMonitor() {
    return new NullProgressMonitor() {
        @Override public void beginTask(String name, final int totalWork) {
            getSplash().getDisplay().syncExec(new Runnable() {
                public void run() {
                        if (fBar != null) fBar.setSelection(40);
                        Image image = fImageList.get(imageIdx++);
                        bgcontainer.setBackgroundImage(image);
                        bgcontainer.setRedraw(true);
                        bgcontainer.update();                 
                    }
                });
            }
    
        @Override public void subTask(String name) {
            final String n = name;
            getSplash().getDisplay().syncExec(new Runnable() {
                String taskname = n;
                public void run() {
                        if (fBar != null && fBar.getSelection() < 100)
                            fBar.setSelection(fBar.getSelection() + 10);
                        if (fBar.getSelection() == 60 || fBar.getSelection() == 80) {
                            if (imageIdx >= fImageList.size()) imageIdx = 0;
                            Image image = fImageList.get(imageIdx++);
                            bgcontainer.setBackgroundImage(image);
                            bgcontainer.setRedraw(true);
                            bgcontainer.update();
                        }
                     }
                 });
             }
        };
    }
    

    【讨论】:

      【解决方案2】:

      我没有试过你的代码,但是当你对Control进行修改时,调用Control.redraw()是不够的,还必须调用Control.update()

      Control.redraw() 请求重绘控件,Control.update() 实际上是重绘它。当您的代码在 UI 线程上运行时需要后者!

      【讨论】:

      • 谢谢 Tonny,我试图在 redraw() 调用之后在 shell 上添加 update() 调用;不幸的是,没有任何改变。还有其他想法吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-09
      • 2010-09-09
      • 2014-11-23
      • 2013-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多