【问题标题】:Adding a div element inside a panel?在面板中添加 div 元素?
【发布时间】:2012-05-17 20:29:57
【问题描述】:

我正在使用 GWT,我正在尝试将 google-maps 添加到我的网站。 因为我想使用 google-maps V3,所以我使用的是 JSNI。 为了在我的网站中显示地图,我需要创建一个 id="map" 的 div 元素并在地图的初始化函数中获取它。我这样做了,效果很好,但它在网页上的位置很有趣,我希望它附加到我在代码中创建的面板上。 所以我的问题是我该怎么做? 我可以在面板中使用 GWT 以某种方式创建 div 吗?

我尝试过像这样创建一个新的 HTMLPanel:

runsPanel.add(new HTMLPanel("<div id=\"map\"></div>"));

其中 runsPanel 是我想要附加到的面板。 但是,当我使用以下初始化函数时,它无法检索 div:

private native JavaScriptObject initializeMap() /*-{

    var latLng = new $wnd.google.maps.LatLng(31.974, 34.813); //around Rishon-LeTsiyon
    var mapOptions = {
        zoom : 14,
        center : latLng,
        mapTypeId : $wnd.google.maps.MapTypeId.ROADMAP
    };
    var mapDiv = $doc.getElementById('map');
    if (mapDiv == null) {
        alert("MapDiv is null!");
    }
    var map = new $wnd.google.maps.Map(mapDiv, mapOptions);
    return map;

}-*/;

(它会弹出警报 - “MapDiv 为空!”)

有什么想法吗? 谢谢

【问题讨论】:

  • 为什么不使用 GWT-Google-APIs 预发布版本:code.google.com/p/gwt-google-apis/issues/detail?id=381#c53
  • 你的runsPanel是什么类型的?当然,您可以在面板内创建div。在你的代码中一切都是正确的。它应该可以正常工作。
  • 它是一个水平面板。然而,它不起作用......
  • 在这种情况下使用 Horizo​​ntalPanel 是不合逻辑的。它被转换成一个表。但尽管如此,您的代码是正确的。寻找对方的错误。

标签: javascript google-maps gwt google-maps-api-3 jsni


【解决方案1】:

您需要确保在加载时调用initializeMap(),以验证 DOM 元素是否可访问。

尝试刷新您的方法并使用另一种技术来创建地图面板:

  1. 扩展 Widget 以定义将用于 Google 地图容器的自定义小部件:

    public class MapPanel extends Widget {
    
        private Element container;
    
        public MapPanel() {
    
            container = DOM.createDiv();
            container.setId("map");
    
            // this is required by the Widget API to define the underlying element
            setElement(container);
        }
    
        @Override
        protected void onLoad() {
            super.onLoad();
    
                initializeMap();
            }
        }
    }
    
  2. 调用初始化:

    runsPanel.add(new MapPanel());
    

还有其他问题,比如id属性,硬编码在JSNI方法中并强制重复代码,以及initializeMap()的正确位置以及是否为JSNI层创建覆盖类型,但仅此而已不在此范围内。

参考资料:

【讨论】:

    【解决方案2】:

    如果您确保在调用 initializeMap() 之前将 runsPanel 附加到 DOM,您的代码可以正常工作。

    你可以用这个简单的入口点来测试它:

    @Override
    public void onModuleLoad() {
    
      final Panel runsPanel = new ...Panel; /* Use the kind of panel you like */
    
      runsPanel.add(new HTMLPanel("<div id=\"map\"></div>"));
    
      RootLayoutPanel.get().add(runsPanel);
    
      initializeMap();
    }
    

    将 HTMLPanel 添加到 runsPanel 是不够的。如果 runsPanel 本身没有附加到 DOM,那么 $doc.getElementById('map') 找不到任何东西。

    注意:确保以某种方式设置“地图”div的高度,否则您将看不到地图。

    【讨论】:

      【解决方案3】:

      您可能想通过使用 UiBinder 来简化事情;在此处查看 Hello World 示例:https://developers.google.com/web-toolkit/doc/latest/DevGuideUiBinder

      UiBinder 允许您编写定义 UI 布局结构的 XML,类似于使用 HTML 布局页面的方式。但是 XML 可以构造小部件,例如按钮等。此外,您可以将名称附加到 XML 元素并在 Java 代码中引用它以将事件处理程序绑定到它等等。它工作得很好,它使代码变得非常简单阅读。

      此外,在这些情况下,UiBinder 可以为您制作原生 HTML 元素并按照您想要的方式嵌套它们,而不必调用方法来制作小部件并将它们放入其他小部件中。然而,此外,UiBinder 文档说 UiBinder 可以更好地使用浏览器本地表示事物的方式,从而产生更高效的代码(来自上面的链接):

      除了是一种更自然、更简洁的 UI 构建方式之外 通过代码做到这一点,UiBinder 还可以让你的应用程序更高效。 浏览器更擅长通过填充大字符串来构建 DOM 结构 将 HTML 转换为 innerHTML 属性,而不是通过一堆 API 调用。 UiBinder 自然地利用了这一点,结果是 构建应用程序最愉快的方式也是构建它的最佳方式。

      我认为此功能可能使浏览器更有可能正确注册您的小部件,以便稍后通过 getElementById() 找到它们。

      您上面的代码在 UiBinder 中可能如下所示:

      <g:HTMLPanel ui:field='my_HTMLPanel'>
        <div ui:field='map_div'>
          <!-- put some HTML here -->
        </div>
      </g:HTMLPanel>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-22
        • 1970-01-01
        • 1970-01-01
        • 2012-02-11
        • 1970-01-01
        • 1970-01-01
        • 2018-10-03
        相关资源
        最近更新 更多