Приложение Eclipse РКП - настраиваемые заставки


В настоящее время я разрабатываю приложение Eclipse RCP, в котором я пытаюсь реализовать пользовательский обработчик экрана-заставки, имеющий индикатор выполнения (поведение, аналогичное индикатору выполнения по умолчанию, который вы можете определить в .определение продукта) и несколько циклических фоновых изображений.

После редактирования расширений основного плагина приложения следующим образом:

[...]
<!-- 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>
[...]

Я пытаюсь реализовать пользовательский класс обработчика splashscreen:

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

Проблема в том, что индикатор выполнения просто работает, пока изображения не показаны. Во время отладки я мог бы проверить, что изображения действительно найдены и загружены, и правильно установлены в оболочке; оболочка просто не перерисовывается. Я что-то упустил?=

2 3

2 ответа:

Я мог бы решить эту проблему на linux и windows, но это не сработало на macos/cocoa (в котором заставка выглядит "скремблированной" на каждой итерации слайд-шоу изображений).

Это было очень просто, просто прикрепив дополнительный композит между оболочкой splash и контейнером, содержащим виджеты; затем измените фоновое изображение на вновь созданном объекте контейнера.

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

Я не пробовал ваш код, но когда вы вносите изменения в Control, недостаточно вызвать Control.redraw(), но вы также должны вызвать Control.update().

Control.redraw() просит, чтобы элемент управления был перерисован, Control.update() фактически перерисовывает его. Последнее необходимо, когда ваш код выполняется в потоке пользовательского интерфейса!