Приложение 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 ответа:
Я мог бы решить эту проблему на 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()
фактически перерисовывает его. Последнее необходимо, когда ваш код выполняется в потоке пользовательского интерфейса!