【问题标题】:GWT Widget not properly set in the DOMGWT Widget 未在 DOM 中正确设置
【发布时间】:2012-12-03 21:59:10
【问题描述】:

我想打印一个扩展 Composite 的 GWT 小部件。此小部件由一个网格组成,其单元格是使用 ListDataProvider 构建的。当用户单击按钮打印时,将构建要打印的小部件。完成后,我启动打印:

    Element element = widgetToPrint.getElement();
    String content = element.getInnerHTML();
    print(content);


    public static native boolean print(String content)
    /*-{
    var mywindow = window.open('', 'Printing', '');
    mywindow.document.write('<html><head><title>Test</title>');
    mywindow.document.write('<link rel="stylesheet" href="/public/stylesheets/ToPrintWidget.css" type="text/css" media="all"/></head><body>');
    mywindow.document.write(content);
    mywindow.document.write('</body></html>');
    mywindow.print();
    return true;
    }-*/;

所以,这是我的问题:

通过这种方法打开的窗口包含了widget的核心(由UI Binder构建),但是缺少一些子...

如果我查看 ListDataProvider 及其相关的 FlowPanel,数据是一致的,即我的列表和 flowPanel 中有几个项目。

因此,它应该在打印窗口上可见... 我认为问题可能与用于打印小部件的方法有关,因此我还尝试在启动打印之前将此小部件添加到对话框中,以查看小部件是否正确构建......确实如此。

所以我的小部件在对话框上显示良好,但如果我尝试通过使用 getElement() 将其 innerHTML 提供给打印方法,则缺少一些小部件......我觉得应该是的小部件当 ListDataProvider 更改未在 DOM 中正确设置时构建...当我将小部件添加到常规组件时它以某种方式工作,但是当我必须直接提供其 innerHTML 时它不起作用...

你有什么想法吗?

提前致谢。

【问题讨论】:

    标签: gwt dom printing


    【解决方案1】:

    小部件不仅仅是它们元素的总和,DOM 元素不仅仅是它们被序列化的字符串。小部件是元素,所有事件都下沉到 dom 以侦听用户的任何更改或交互。然后,元素具有回调函数或当用户与它们交互时调用的处理程序。

    通过序列化元素(即调用getInnerHTML()),您只读取了 dom 的结构,而不是回调,也不是 CSS 设置的样式。可能不应该期望这可以正常工作,并且正如您的经验所证明的那样,事实并非如此。

    由于这只是您尝试创建的打印窗口,因此事件处理可能不是问题。您只希望能够查看该组小部件中的内容,但不能与之交互。样式可能是这里的主要问题(尽管您的问题没有指定“缺少一些孩子”并没有告诉我们缺少什么,或者给我们更多关于为什么的线索......) - 您正在添加一个样式表在您的 JSNI 代码中,但 CellTable(我假设您正在使用它,因为您引用了 ListDataProvider)需要额外的 CssResource 实例才能正确显示。我不确定您如何劫持那些在新窗口中绘制。

    你只是用它来打印内容,而不是让用户直接与数据交互吗?如果是这样,请考虑另一种方法 - 使用 SafeHtmlBuilder 创建一个巨大的、正确转义的内容字符串以在新窗口中绘制。

    【讨论】:

    • 感谢您的快速回答。您对窗口是正确的,它的目的是打印,不需要与用户交互。正如你所建议的,我将尝试使用 SafeHtmlBuilder,但如果它也给出了一个字符串,我想知道为什么这个可能包含丢失的孩子?否则,关于您关于我的主题的问题:失踪的孩子是与 CellTable 相关的孩子。当我查看元素时,我可以看到它的 CellList 不是空的。因此,我假设该小部件已正确构建,实际上它在对话框中显示良好......而不是在打印窗口上
    • 我已经搜索了一下,但我不知道如何使用 SafeHTMLBuilder 从小部件中获取字符串...你能给我基本的想法吗?
    • 对不起,如果我不清楚 - SafeHtmlBuilder 旨在替代构建小部件,因为小部件确实不是按照您要求的方式操作的。 Thomas Broyer 关于克隆小部件所有节点的建议已经接近,但如果使用 CellGrid/DataTable/etc 或任何其他依赖 CssResources 来运行的小部件,您仍然会错过那些样式,这些样式被添加为小部件是构造的,在你的情况下更重要的是,构造到 错误的窗口
    【解决方案2】:
    String content = element.toString();
    

    这将包括节点中的所有层次结构元素。

    提醒一下,所有 GWT 处理程序都不起作用,您必须使用 DOM 接收所有事件。

    【讨论】:

    • 您好,感谢您的回答。我刚试了...但它也不起作用。
    • @user1873805 你在构造函数中初始化了所有的小部件内容吗?不要将代码放在 onLoad 方法中。
    • 所有小部件都是由构造函数构建的,onLoad() 中没有任何内容。而且,widget不监听任何事件,即widget一旦构建,他就不会改变。
    • @user1873805 这很奇怪。我尝试使用与您在 GWT 中所做的相同的事情,并且效果很好。 getInnerHTML 肯定不能正常工作,但 toString 为我工作。
    • @user1873805 尝试使用警告框或在某处打印以尝试toString 是否可以打印您丢失的小部件的代码。如果不是,那么问题就出在小部件初始化上。
    【解决方案3】:

    您可能想要获取 外部 HTML 而不是 内部

    不幸的是,GWT 没有getOuterHTML,但它相对容易模拟

    • 如果您的小部件是元素中唯一的子元素,则只需获取父元素的内部 HTML (w.getElement().getParentElement().getInnerHTML())
    • 否则,克隆您的小部件节点,将其添加到新创建的父元素中,您将能够从中获取内部 HTML:

      DivElement temp = Document.get().createDivElement();
      temp.appendChild(w.getElement().cloneNode(true));
      return temp.getInnerHTML();
      

    【讨论】:

    • 你好。如果我跟着你,你建议写: String content = data.getString();而不是 String content = data.getInnerHTML(); ?我刚试了一下,也不管用……不过还是谢谢
    • 对不起,简短的回答,我在手机上。请参阅更新的答案。正如 javadoc 所说,toString() 只能用于调试。
    • 没问题。我已经将我的小部件打印在一个不包含任何其他内容的流程面板中。然后我得到了你建议的outerHTML。它看起来像: PrintWidget printWidget = new PrintWidget();打印机.add(printWidget); printWidget.update();元素元素 = printWidget.getElement().getParentElement();字符串内容 = element.getInnerHTML(); Window.alert(内容);打印(内容); String 内容中仍然没有任何内容,当我用 firebug 检查小部件时,它是空的...
    【解决方案4】:

    首先感谢您的回答,它帮助我解决了这个问题。 我几乎解决了这个问题:

    首先,我不再使用 ListDataProvider,因为我不清楚何时以及如何刷新视图。相反,我手动添加了我的小部件,这是有道理的,因为它们无论如何都不会移动。

    然后,我使用通用 CSS 样式表定义小部件的样式。但是,为了做到这一点,我不能依赖 CssResource,这是我过去使用 GWT 的方式。我认为这是由于 JS 方法被这种样式迷失了......相反,我必须在静态 CSS 样式表中指定所有内容,并将其提供给 JS。

    它工作得很好,也就是说,我有我的小部件,有它们的样式,我可以打印它。

    但是…… 一些小部件的颜色取决于它们所代表的对象的颜色。因此,我无法编写通用的 CSS 样式表...正如我所说,我无法使用 CssResource 添加样式...您对处理该问题有什么想法吗?

    为了确保我清楚我添加样式的方式,这里有一个示例:

        Label l = new Label("Here is a cell in my grid to be printed");
        l.addStyleName("PrintLineCell-kind_1");
    

    在公共 CSS 样式表中:

        .PrintLineCell-kind_1{
            background-color: red;
        }
    

    我希望有更好的方法,而不是写 300 种样式来覆盖 300 种不同的颜色...

    【讨论】:

    • label.getElement().getStyle().setBackgroundColor("red") 之类的内容可能适用于您的颜色问题。
    • 是的!是的 !!是的 !!太感谢了 !这可能不是最好的方法,但效果很好,这就是我所要求的!再次感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 2018-12-26
    • 2013-05-22
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多