Vaadin – 如何从单个按钮打开BrowserWindowOpener

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

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

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

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

 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因为你第一次点击它不会工作。 然后我想如果我在BrowserWindowOpener之外声明了ClickListener ,在链接PrintButtonClickListener的类中,使用虚拟资源:

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

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

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

但是,这里的问题是第一次单击会生成一个空白页面。

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

最后,我希望能够在ClickListener完成所有这些ClickListener ,这与其他所有内容完全分离。

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

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

请注意,此方法已弃用。

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

不要认为可以在一个按钮中使用BrowserWindowOpener而不用乱砍JavaScript。

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

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

  2. 仅在真正需要时生成pdf

     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生成:

 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方法:

 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文件时都必须更改文件名以避免缓存问题。