В одном из моих приложений я создавал графики и диаграммы в SWT. Пользователь смог экспортировать их в изображение с указанием размера и формата. Мое решение состояло в том, чтобы взять GC составной диаграммы и перерисовать ее на новый составной экран, а затем экспортировать вновь собранный композит.
Вот мой класс, который достиг этого:
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Composite;
/**
* The class used for writing an {@link Composite} to an image file
*
* @author David L. Moffett
*
*/
public class CompositeImageWriter
{
/**
* Redraws the composite to the desired size off-screen and then writes that
* composite as an image to the desired location and in the desired format
*
* @param absolutePath
* the absolute path to the desired output file
* @param compositeToDraw
* the composite to be written to file as an image
* @param width
* the desired width in pixels that the composite should be redrawn
* to
* @param height
* the desired height in pixels that the composite should be redrawn
* to
* @param imageType
* an int representing the type of image that should be written
*/
public static void drawComposite(String absolutePath, Composite compositeToDraw, int width,
int height, int imageType)
{
Image image = new Image(compositeToDraw.getDisplay(), width, height);
GC gc = new GC(image);
int originalWidth = compositeToDraw.getBounds().width;
int originalHeight = compositeToDraw.getBounds().height;
compositeToDraw.setSize(width, height);
compositeToDraw.print(gc);
compositeToDraw.setSize(originalWidth, originalHeight);
ImageLoader loader = new ImageLoader();
loader.data = new ImageData[] { image.getImageData() };
loader.save(absolutePath, imageType);
image.dispose();
gc.dispose();
}
}
Для вашего случая желание всегда экспортировать в определенном размере, просто замените аргументы ширины и высоты с соответствующими константами.
Edit 1
Я хотел бы добавить, что int imageType
аргумент соответствующий SWT модификатор (например: SWT.IMAGE_PNG
, SWT.IMAGE_JPEG
, SWT.IMAGE_BMP
, и т.д ...).
Edit 2
Я обновил статическую ссылку динамически получить дисплей от compositeToDraw. Кроме того, вот пример, который я поставил вместе, который использует CompositeImageWriter
, которые вы можете использовать для отладки вопроса:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
public class CompositeToWrite extends Composite
{
private int width, height;
private Label l;
public CompositeToWrite(Composite parent, int style)
{
super(parent, style);
this.setLayout(new GridLayout(1, true));
this.addListener(SWT.Resize, new Listener()
{
@Override
public void handleEvent(Event event)
{
updateText();
}
});
Button b = new Button(this, SWT.NONE);
b.setText("Export as image (500, 500)");
b.addListener(SWT.Selection, new Listener()
{
@Override
public void handleEvent(Event event)
{
CompositeImageWriter.drawComposite("./img/output.png", CompositeToWrite.this, 500, 500,
SWT.IMAGE_PNG);
}
});
l = new Label(this, SWT.CENTER);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.verticalAlignment = SWT.CENTER;
l.setLayoutData(gd);
updateText();
}
protected void updateText()
{
width = this.getBounds().width;
height = this.getBounds().height;
l.setText("My label is centered in composite (" + width + ", " + height + ")");
}
}
В случае этого примера я создаю простой композит, который когда-то добавленный к оболочке будет выглядеть что-то вроде этого:
Когда я нажимаю кнопку, она изменяет размер композита на 500 x 500 и записывает измененный композит в файл. В результате эта картина:
я должен отметить, что я заметил композитное мерцание, когда кнопка нажата, так что это не может происходить полностью в фоновом режиме или «выкл экране», как я первоначально предложил.
Спасибо за ответ, но можете ли вы более подробно описать, как вы создали экранный экран? Я еще не нашел решение для этого ... И после установки размера композита он автоматически изменяется или мне нужно вызвать какой-то метод для этого? – tom1991te
Итак, в этом случае «compositeToDraw» будет вашей панелью инструментов, в первой строке мы создадим новое изображение с требуемой шириной и высотой, а затем создадим новый графический компонент для этого изображения, затем мы изменим размер исходного композита, а затем скажем его пишите себе в новый графический компонент для изображения. Наконец, мы вернем исходный композитный исходный размер, а затем напишем новое измененное изображение в файл.Изменение размера оригинального композита никогда не реализуется «на экране», поскольку родитель исходного композита не обновляется, поэтому комментарий «за пределами экрана». – Automaton
ok Я вижу, что вы имеете в виду сейчас с частью «вне экрана», но это все еще не работает для меня. После изменения размера композита и его печати на изображение изображение имеет нужный размер, но композит по-прежнему находится в исходном размере ... Это означает, что на изображении сейчас много свободного места. Любые идеи, что я делаю неправильно? – tom1991te