Vaadin - 如何从单个按钮打开BrowserWindowOpener [英] Vaadin - How to open BrowserWindowOpener from a SINGLE BUTTON

查看:296
本文介绍了Vaadin - 如何从单个按钮打开BrowserWindowOpener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Vaadin如何打印动态生成的示例PDF 他们有两步法,首先你点击 OkButton 然后点击 PrintButton 。问题是他们打开PDF的代码依赖于创建一个新的 BrowserWindowOpener ,然后扩展 Print 按钮。 ClickListener 代表 OKButton 。换句话说,他们有:

In the Vaadin example of how to print a dynamically generated PDF they have a two step approach, first you click on the OkButton and then the PrintButton. The problem is that their code to open the PDF relies on creating a new BrowserWindowOpener which then extends the Print button in the ClickListener for the OKButton. In other words they have:

okButton.addClickListener(new ClickListener() 
 {
    @Override
    public void buttonClick(ClickEvent event) 
    {
        // Dynamically generate PDF - this is greatly simplified.
        StreamResource pdfResource = new PdfStreamResource();
        BrowserWindowOpener opener = new BrowserWindowOpener(pdfResource);
        opener.extend(printButton);
    }
}

这很好,因为打印按钮现在链接到 BrowserWindowOpener 并立即打开窗口/单击 PrintButton 时的选项卡。

This is great because the Print button is now linked to BrowserWindowOpener and will immediately open the window/tab when you click on the PrintButton.

我遇到的问题是我不想要 OkButton ,我只想要一个 PrintButton 。在这种情况下我无法添加

The problem I have is that I don't want an OkButton, I just want to have a PrintButton. In this case I can't add

printButton.addClickListener(new ClickListener() 
 {
    @Override
    public void buttonClick(ClickEvent event) 
    {
        // Dynamically generate PDF - this is greatly simplified.
        StreamResource pdfResource = new PdfStreamResource();
        BrowserWindowOpener opener = new BrowserWindowOpener(pdfResource);
        opener.extend(printButton);
    }
}

ClickListener FOR THE PrintButton 因为第一次单击它不会起作用。然后我想到如果我在 ClickListener 之外的 BrowserWindowOpener 之外的链接 PrintButton ClickListener ,使用虚拟资源:

In the ClickListener FOR THE PrintButton because the first time you click it wont work. I then thought what if I had BrowserWindowOpener declared outside of the ClickListener, in the class that links the PrintButton and ClickListener, using something a dummy resource:

BrowserWindowOpener opener = new BrowserWindowOpener("");
opener.extend(printButton);
PrintClickListener printClickListener = new PrintClickListener(opener);
printButton.addClickListener(printClickListener);

然后将开启者传递给 ClickListener 以便我可以执行以下操作:

And then pass the opener to the ClickListener so that I could do something like:

printButton.addClickListener(new ClickListener() 
 {
    @Override
    public void buttonClick(ClickEvent event) 
    {
        // Dynamically generate PDF - this is greatly simplified.
        StreamResource pdfResource = new PdfStreamResource();
        opener.setResource(pdfResource);
    }
}

但问题是,第一次点击会生成一个空白页。

However the issue here is that the first click generates a blank page.

我的问题是如何让示例在哪里工作?动态生成的PDF只用一个按钮即可推送到浏览器窗口。 BrowserWindowOpener 的所有示例似乎总是使用两个按钮。并且声明的示例类层次结构中较高的对我来说不起作用,它总是一个初始的空白页面。

My question is how can I get the example working where the dynamically generated PDF is pushed to the browser window with just a SINGLE BUTTON. All the examples for BrowserWindowOpener seem to always use two buttons. And the examples that declare it higher in the class hierarchy don't work for me, it's always an initial blank page.

最后,我希望能够在 ClickListener 中完成所有这一切,这完全与其他一切。

Lastly, I would love to be able to do all this within the ClickListener, that is totally decoupled from everything else.

推荐答案

摆脱 BrowserWindowOpener 并使用 UI.getPage()。open()查看你的pdf文件。

Get rid of BrowserWindowOpener and use UI.getPage().open() to view your pdf file.

getUI().getPage().open(resource, "_blank", false);

请注意,方法已被弃用。


从Vaadin 7.0.0开始,在页面中打开资源的功能已被基于字符串URL的类似方法所取代。这是因为资源的使用在内存管理方面存在问题,并且在某些浏览器中具有安全功能。建议改为使用Link开始下载。

As of Vaadin 7.0.0, the functionality for opening a Resource in a Page has been replaced with similar methods based on a String URL. This is because the usage of Resource is problematic with memory management and with security features in some browsers. Is is recommended to instead use Link for starting downloads.

不要认为只能在一个按钮中使用 BrowserWindowOpener 没有黑客入侵JavaScript。

Don't think it is possible to use BrowserWindowOpener in one button only without hacking in JavaScript.

编辑:
我使用BrowserWindowOpener取得了预期的效果。每次请求BrowserWindowOpenerState时,我都扩展了类并添加了pdf生成。问题是我搜索了一个在点击之后和BrowserWindowOpener打开新标签之前调用的方法。我能找到的唯一方法是getState() - 并且仅当组件的状态为脏时。我还必须在覆盖getState方法中添加一个标志,因为:

I've achieved desired effect using BrowserWindowOpener. I've extended the class and added pdf generation every time when BrowserWindowOpenerState is requested. The thing is that I've searched for a method that is invoked after the click and before BrowserWindowOpener opens up new tab. The only method I could find is getState() - and only when the state of the component is dirty. I had to also add a flag in overriden getState method because:


  1. setResource方法也调用getState()方法,所以我有无限循环

  1. setResource method invoke getState() method too, so I had infinite loop

仅在真正需要时生成pdf

to generate pdf only when its really needed

public class BrowserWindowOpenerWithBeforeClick extends BrowserWindowOpener
{

private boolean pdfGenerated = false;

public BrowserWindowOpenerWithBeforeClick(String url)
{
    super(url);
}

@Override
protected BrowserWindowOpenerState getState(boolean markAsDirty) {
    if(!pdfGenerated){
        StreamResource resource = ((RfgUI) UI.getCurrent()).getResource();
        pdfGenerated = true;
        this.setResource("url",resource);
    }
    return (BrowserWindowOpenerState) super.getState(markAsDirty);
}

public void setPdfGenerated(boolean generated){
    this.pdfGenerated = generated;
}
}


在主UI类中生成pdf:

And pdf generation in your main UI class:

void pdfgeneration(final VerticalLayout layout)
{
    name.setValue("Slartibartfast");
    final Button ok = new Button("OK");
    ok.setId("ok-button");
    final BrowserWindowOpenerWithBeforeClick bwo = new BrowserWindowOpenerWithBeforeClick("");
    bwo.extend(ok);
    name.addValueChangeListener(new ValueChangeListener()
    {
        @Override
        public void valueChange(ValueChangeEvent event)
        {
            bwo.setPdfGenerated(false);
            bwo.markAsDirty();
        }
    });
    layout.addComponent(name);
    layout.addComponent(ok);
}

和getResource方法:

And getResource method:

public StreamResource getResource()
{
    StreamSource source = new MyPdfSource((String) name.getValue());
    String filename = new Random().nextInt() + "pdf_printing_example.pdf";
    StreamResource resource = new StreamResource(source, filename);
    resource.setMIMEType("application/pdf");
    resource.setCacheTime(0);
    resource.getStream().setParameter("Content-Disposition", "attachment; filename=" + filename);
    return resource;
}

请注意,每次我都必须更改文件名我生成新的pdf文件以避免缓存问题。

Notice that I had to change the filename everytime I generate new pdf file to avoid caching problems.

这篇关于Vaadin - 如何从单个按钮打开BrowserWindowOpener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆