Java 将合成输出到独立于屏幕分辨率的图像

Java 将合成输出到独立于屏幕分辨率的图像,java,swt,Java,Swt,SWT中是否有方法将合成输出到始终具有相同大小/分辨率的图像?问题是,我们有一个仪表板,当在具有不同显示大小/分辨率的屏幕上打开时,它看起来总是不同的。现在的问题是,我是否可以将仪表板导出到具有固定大小的图像中,并且无论创建的屏幕大小/分辨率如何,它的外观始终相同 目前我们是这样做的,但如前所述,这取决于创建它的显示器: Image image = new Image(Display.getCurrent(), this.content.getBounds().width, this.conte

SWT中是否有方法将合成输出到始终具有相同大小/分辨率的图像?问题是,我们有一个仪表板,当在具有不同显示大小/分辨率的屏幕上打开时,它看起来总是不同的。现在的问题是,我是否可以将仪表板导出到具有固定大小的图像中,并且无论创建的屏幕大小/分辨率如何,它的外观始终相同

目前我们是这样做的,但如前所述,这取决于创建它的显示器:

Image image = new Image(Display.getCurrent(), this.content.getBounds().width, this.content.getBounds().height);
ImageLoader loader = new ImageLoader();
FileOutputStream fileOutputStream = new FileOutputStream(file);

GC gc = new GC(image);
this.content.print(gc);

gc.dispose();

loader.data = new ImageData[] { image.getImageData() };
loader.save(fileOutputStream, imageFormat);
fileOutputStream.close();
例如,是否有某种方法可以创建具有特定分辨率的虚拟屏幕,该屏幕实际上不显示,仅用于导出仪表板?
任何帮助或指点都将不胜感激。

在我的一个应用程序中,我正在用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();
  }
}
对于希望始终以特定大小导出的情况,只需使用适当的常量替换宽度和高度参数

编辑1

我应该补充一点,
int imageType
参数是相应的SWT修饰符(例如:
SWT.IMAGE\u PNG
SWT.IMAGE\u JPEG
SWT.IMAGE\u BMP
,等等)

编辑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 + ")");
  }

}
在本例中,我创建了一个简单的组合,一旦添加到shell中,它的外观如下所示:

当我单击按钮时,它会将合成的大小调整为500 x 500,并将调整大小的合成写入文件。结果是这张图片:


我应该注意到,我确实在单击按钮时注意到了复合闪烁,因此这可能不会完全发生在背景中,也不会像我最初建议的那样发生在“屏幕外”。

谢谢您的回答,但您能否更详细地描述一下您是如何创建“屏幕外”显示的?我还没有找到解决这个问题的办法。。。在设置合成图的大小后,它是自动调整大小还是需要调用某种方法?因此,在这种情况下,“compositeToDraw”将是您的仪表板,在第一行中,我们创建一个具有所需宽度和高度的新图像,然后为该图像创建一个新的图形组件,接下来,我们调整原始组合的大小,然后告诉它将自己写入图像的新图形组件。最后,我们将原始合成设置回其原始大小,然后将新调整大小的图像写入文件。原始组合的大小调整从未在“屏幕上”实现,因为原始组合的父级未被更新,因此出现了“屏幕外”注释。好的,我明白你现在对“屏幕外”部分的意思,但它仍然不适用于我。调整合成大小并将其打印到图像后,图像本身具有正确的大小,但合成仍保持其原始大小。。。这意味着现在图像上有很多空白。你知道我做错了什么吗?嗯,不太清楚为什么在没有看到你如何调用这个方法的细节的情况下,它可能对你不起作用。我用一些示例代码更新了我的答案,您可以使用这些代码来调试为什么它不适合您。如果你找不到这个问题,你可能想更新你的初始问题,包括一个更完整的例子,说明你是如何使用这个类的。谢谢,我现在已经让它工作了。看起来问题是我有嵌套的复合材料,而仅仅调整外部的尺寸并不能解决这个问题。。。