0

我需要在客户端打印一张图片。我用这个作为模板。我的 PrintUI 如下所示:

@Override
protected void init(VaadinRequest request) {
    Item item = ..get item ..

    StreamResource imageStream = ... build image dynamically ...
    Image image = new Image(item.getName(), imageStream);
    image.setWidth("100%");
    setContent(image);
    setWidth("100%");

    // Print automatically when the window opens
    JavaScript.getCurrent().execute("setTimeout(function() {print(); self.close();}, 0);");
}

到目前为止,这在 IE 中有效,但在 chrome 中,它会打开显示空白页面的打印预览。问题是图像以某种方式加载,chrome 不会等待它并立即开始打印预览。

为了验证这一点,我尝试了:(设置 5 秒超时)

JavaScript.getCurrent().execute("setTimeout(function() {print(); self.close();}, 0);");

然后它可以在 IE 和 Chrome 中运行,但它当然是一个丑陋的 hack,如果连接速度低于 5 秒,那么它将再次失败。

在纯 JS 中它会像这样工作,但我不确定如何在 cient-side js 中引用来自 vaadin 的元素。有任何想法吗?

4

1 回答 1

3

您可以使用AbstractJavascriptExtension

示例扩展类:

@JavaScript({ "vaadin://scripts/connector/wait_for_image_load_connector.js" })
public class WaitForImageLoadExtension extends AbstractJavaScriptExtension {

    private List<ImageLoadedListener> imageLoadedListeners = new ArrayList<>();

    public interface ImageLoadedListener {
        void onImageLoaded();
    }

    public void extend(Image image) {
        super.extend(image);
        addFunction("onImageLoaded", new JavaScriptFunction() {

            @Override
            public void call(JsonArray arguments) {
                for (ImageLoadedListener imageLoadedListener : imageLoadedListeners) {
                    if (imageLoadedListener != null) {
                        imageLoadedListener.onImageLoaded();
                    }
                }
            }
        });
    }

    public void addImageLoadedListener(ImageLoadedListener listener) {
        imageLoadedListeners.add(listener);
    }
}

和 javascript 连接器(放置在 wait_for_image_load_connector.js 中)与您链接的等待方法:

window.your_package_WaitForImageLoadExtension = function() {
        var connectorId = this.getParentId();
        var img = this.getElement(connectorId);

        if (img.complete) {
            this.onImageLoaded();
        } else {
            img.addEventListener('load', this.onImageLoaded)
            img.addEventListener('error', function() {
                alert('error');
            })
        }

    }

然后你可以做这样的事情:

Image image = new Image(item.getName(), imageStream);

WaitForImageLoadExtension ext = new WaitForImageLoadExtension();
ext.extend(image);
ext.addImageLoadedListener(new ImageLoadedListener() {

    @Override
    public void onImageLoaded() {
        JavaScript.eval("print()");
    }
});

在您的情况下,当调用print()是您在加载图像后唯一想做的事情时,您也可以在没有服务器端侦听器的情况下通过在连接器中调用它来执行此操作:

if (img.complete) {
    print();
} else {
    img.addEventListener('load', print)
    img.addEventListener('error', function() {
        alert('error');
    })
}
于 2017-04-27T20:17:10.717 回答