【问题标题】:Export composite to image independent of the screen resolution将合成导出到独立于屏幕分辨率的图像
【发布时间】:2015-11-28 02:37:33
【问题描述】:

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

例如,是否有某种方法可以创建具有特定分辨率的虚拟屏幕,但实际上并没有显示,仅用于导出仪表板? 任何帮助或指示将不胜感激。

【问题讨论】:

    标签: java swt


    【解决方案1】:

    在我的一个应用程序中,我在 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_PNGSWT.IMAGE_JPEGSWT.IMAGE_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 + ")");
      }
    
    }
    

    在这个例子中,我创建了一个简单的组合,一旦添加到外壳中,它看起来像这样:

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

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

    【讨论】:

    • 感谢您的回答,但您能否更详细地描述一下您是如何创建“屏幕外”显示的?我还没有找到解决方案……在设置复合材料的大小后,它会自动调整大小还是我需要为此调用一些方法?
    • 所以在这种情况下,“compositeToDraw”将是您的仪表板,在第一行我们创建一个具有所需宽度和高度的新图像,然后为该图像创建一个新的图形组件,接下来我们调整大小原始合成然后告诉它将自己写入图像的新图形组件。最后,我们将原始合成设置回其原始大小,然后将新调整大小的图像写入文件。原始合成的大小调整永远不会在“屏幕上”实现,因为原始合成的父级没有被更新,因此是“屏幕外”注释。
    • 好的,我明白你现在对“屏幕外”部分的意思了,但它仍然对我不起作用。调整合成尺寸并将其打印到图像后,图像本身具有正确的尺寸,但合成仍保持其原始尺寸......这意味着现在图像上有很多空白空间。任何想法我做错了什么?
    • 嗯,如果没有看到您如何调用该方法的详细信息,不太确定为什么它可能不适合您。我用一些示例代码更新了我的答案,您可以使用这些代码来调试它为什么不适合您。如果您找不到问题,您可能需要更新您的初始问题,以包含一个更完整的示例,说明您如何使用该课程。
    • 谢谢我现在开始工作了。问题似乎是我有嵌套的复合材料,只是调整外部复合材料的大小并不能解决问题......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    相关资源
    最近更新 更多