環境:
1、Glassfish 3.1
2、primefaces 3.0.1
要件:
1、「corpInfoMap」という名前の複合コンポーネントを開発します。これは、Googleマップ内の企業の場所を「マーカー」として表示します。ユーザーがマーカーをクリックすると、mapInfoWindowに企業の情報が表示されます。
2、「corpInfoMapDialog」という名前の別の複合コンポーネントを開発します。これはap:dialogに「corpInfoMap」が含まれています。
問題:
マップは、ページでもダイアログでも優れた機能を発揮します。しかし、ユーザーがマップ内のマーカーをクリックすると、次のようになります。
リスナーメソッドに渡される「OverlaySelectEvent」(イベント)はNULLです。したがって、「event.getgetOverlay()」はNullPonterExceptionをスローします。
コード:
1 corpInfoMap.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
>
<cc:interface displayName="单位地理信息">
<cc:attribute name="mapModel" required="true" displayName="地理信息Model,com.ui.fwjg.viewModel.CorporationMapModel类型" />
<cc:attribute name="selectedListener" required="true" method-signature="void method(org.primefaces.event.map.OverlaySelectEvent)" displayName="选择锚点的方法" />
</cc:interface>
<cc:implementation>
<f:view contentType="text/html">
<p:gmap zoom="#{cc.attrs.mapModel.zoom}"
type="HYBRID"
center="#{cc.attrs.mapModel.centerWd},#{cc.attrs.mapModel.centerJd}"
style="width:#{cc.attrs.mapModel.width}px;height:#{cc.attrs.mapModel.height}px;"
model="#{cc.attrs.mapModel.model}"
>
<p:ajax event="overlaySelect" listener="#{cc.attrs.selectedListener}"></p:ajax>
<p:gmapInfoWindow rendered="#{cc.attrs.mapModel.selectedMarker != null}" maxWidth="#{cc.attrs.mapModel.width / 2}">
<p:outputPanel style="text-align:center;display:block;margin:auto:" rendered="#{cc.attrs.mapModel.selectedMarker != null}">
<h:panelGroup style="width:100%;font-size:1.5em;line-height:2em;font-weight:bold;text-align:center;">
#{cc.attrs.mapModel.selectedMarker.data.dwmc}
</h:panelGroup>
<h:panelGroup layout="block" styleClass="com-ui-clearboth"></h:panelGroup>
<h:graphicImage rendered="#{not empty cc.attrs.mapModel.selectedMarker.data.dwsltFile}"
style="max-width:#{cc.attrs.mapModel.width / 2};display:block;margin:20px auto;"
url="/file.ui?f=#{cc.attrs.mapModel.selectedMarker.data.dwsltFile}"></h:graphicImage>
<h:outputText value="#{mapBean.marker.title}" />
<h:panelGroup layout="block" styleClass="com-ui-clearboth"></h:panelGroup>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}"
value="<p style="font-size:1em;line-height:1.5em;text-indent:2em;">"
escape="false"></h:outputText>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}" value="#{cc.attrs.mapModel.selectedMarker.dwjj}">
</h:outputText>
<h:outputText rendered="#{not empty cc.attrs.mapModel.selectedMarker.dwjj}" value="</p>" escape="false"></h:outputText>
</p:outputPanel>
</p:gmapInfoWindow>
</p:gmap>
</f:view>
</cc:implementation>
2 corpInfoMapDialog.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:comuicommon="http://java.sun.com/jsf/composite/components/ui/common">
<!-- INTERFACE -->
<cc:interface displayName="单位地理信息窗口">
<cc:attribute name="mapModel" required="true" displayName="地理信息Model,com.ui.fwjg.viewModel.CorporationMapModel类型" />
<cc:attribute name="selectedListener" required="true" method-signature="void method(javax.faces.component.behavior.AjaxBehavior)" displayName="选择锚点的方法" />
<cc:attribute name="dialogId" default="corpInfoMapDialog" displayName="对话框的ID" />
</cc:interface>
<cc:implementation>
<p:dialog header="单位地理信息" widgetVar="#{cc.attrs.dialogId}" id="#{cc.attrs.dialogId}" width="#{cc.attrs.mapModel.width}">
<h:panelGroup rendered="#{cc.attrs.mapModel != null and cc.attrs.mapModel.model != null and (not empty cc.attrs.mapModel.model.markers)}" layout="block">
<comuicommon:corpInfoMap mapModel="#{cc.attrs.mapModel}" selectedListener="#{cc.attrs.selectedListener}"/>
</h:panelGroup>
<h:panelGroup rendered="#{not (cc.attrs.mapModel != null and cc.attrs.mapModel.model != null and (not empty cc.attrs.mapModel.model.markers))}"
layout="block" style="font-size:2em;text-align:center;">
该单位无地理信息。
</h:panelGroup>
</p:dialog>
</cc:implementation>
</html>
3バッキングビーンズ(そのうちの1つ):
@ManagedBean
@ViewScoped
public class JlltWssbDjjsbEditPage implements Serializable{
... // a lot of lines
private CorporationMapModel corporationMapModel;
@PostConstruct
public void init() {
corporationMapModel = new CorporationMapModel();
... // other codes, have no business with corporationMapModel.
}
// the OverlaySelectEvent listener method
// when user click the marker in map, this method is invoked, but the parameter "evnet" is null.
public void setSelectedMarker(OverlaySelectEvent event){
corporationMapModel.onMarkerSelect(event);
}
public CorporationMapModel getCorporationMapModel() {
return corporationMapModel;
}
public void setCorporationMapModel(CorporationMapModel corporationMapModel) {
this.corporationMapModel = corporationMapModel;
}
// reset the jsb, reset the corporationMapModel's properties(only it's properties, neither it nor the mapModel in it.)
public void setJsb(JlltWssbDjjsb jsb) {
this.jsb = jsb;
Corporation corporation = jsb == null ? null : (jsb.getWineInfo() == null ? null : jsb.getWineInfo().getCorporation());
corporationMapModel.resetModel(corporation);
setShowHistory(jsb != null);
initWineInfo();
}
... // a lot of lines, have no business with
}
4 CorporationMapModel.java
public class CorporationMapModel implements Serializable{
private List<Corporation> corporations; // 企业列表 corporation list
private MapModel model; // 地理信息Model primefaces map model
private String centerJd; // 地图中间位置-经度 lng
private String centerWd; // 地图中间位置-维度 lat
private String zoom; // 地图缩放级别 gmap zoom
private Marker selectedMarker; // 被选择的Marker selected marker(overlay)
private int width = 600; // the width(px) of the map
private int height = 480; // the height(px) of the map
public void resetModel(Corporation corporation) {
List<Corporation> corporations = new ArrayList<Corporation>();
if(corporation != null){
corporations.add(corporation);
}
setCorporations(corporations);
}
public void resetModel(List<Corporation> corporations) {
corporations = corporations == null ? new ArrayList<Corporation>() : corporations;
setCorporations(corporations);
}
private void calInfosByCorporations() {
if(model == null)
model = new DefaultMapModel();
model.getMarkers().clear();
if (corporations != null && corporations.size() > 0) {
for (Corporation corporation : corporations) {
CorporationMapInfo mapInfo = CorporationMapInfo.generateNewCorporationMapInfo(corporation);
if (mapInfo != null) {
model.addOverlay(mapInfo);
}
}
List<Marker> markers = model.getMarkers();
if (markers != null && markers.size() > 0) {
double maxWd = 0D;
double minWd = 0D;
double maxJd = 0D;
double minJd = 0D;
for (int i = 0; i < markers.size(); i++) {
Marker marker = markers.get(i);
if (i == 0) {
maxWd = marker.getLatlng().getLat();
minWd = marker.getLatlng().getLat();
maxJd = marker.getLatlng().getLng();
minJd = marker.getLatlng().getLng();
} else {
double wd = marker.getLatlng().getLat();
double jd = marker.getLatlng().getLng();
maxWd = maxWd < wd ? wd : maxWd;
maxJd = maxJd < jd ? jd : maxJd;
minWd = minWd > wd ? wd : minWd;
minJd = minJd > jd ? jd : minJd;
}
}
BigDecimal centerWd = new BigDecimal((maxWd + minWd) / 2D);
BigDecimal centerJd = new BigDecimal((maxJd + minJd) / 2D);
centerWd = centerWd.setScale(6, BigDecimal.ROUND_HALF_UP);
centerJd = centerJd.setScale(6, BigDecimal.ROUND_HALF_UP);
setCenterWd(centerWd.toPlainString());
setCenterJd(centerJd.toPlainString());
zoom = GoogleMapZoom.getZoom(maxWd, minWd, maxJd, minJd, width, height);
}
}
}
public void onMarkerSelect(OverlaySelectEvent event) {
selectedMarker = (Marker) event.getOverlay();
}
public List<Corporation> getCorporations() {
return corporations;
}
public void setCorporations(List<Corporation> corporations) {
corporations = corporations == null ? new ArrayList<Corporation>() : corporations;
this.corporations = corporations;
calInfosByCorporations();
}
public MapModel getModel() {
return model;
}
public String getCenterJd() {
return centerJd;
}
public void setCenterJd(String centerJd) {
this.centerJd = centerJd;
}
public String getCenterWd() {
return centerWd;
}
public void setCenterWd(String centerWd) {
this.centerWd = centerWd;
}
public String getZoom() {
return zoom;
}
public void setZoom(String zoom) {
this.zoom = zoom;
}
public Marker getSelectedMarker() {
return selectedMarker;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public void setModel(MapModel model) {
this.model = model;
}
public void setSelectedMarker(Marker selectedMarker) {
this.selectedMarker = selectedMarker;
}
}
5 js.xhtml("js"は"javascript"ではなく"reduce"を意味します)、このxhtmlファイルの重要な部分:
<h:form id="dwMapForm">
<comuicommon:corpInfoMapDialog
mapModel="#{jlltWssbDjjsbEditPage.corporationMapModel}"
selectedListener="#{jlltWssbDjjsbEditPage.setSelectedMarker(org.primefaces.event.map.OverlaySelectEvent)}"
dialogId="dwMapDialog"
/>
</h:form>
私がしたこと:
1、私はたくさんググったが、答えはありません。
2、デバッグしましたが、イベントオブジェクトがprimefacesによって生成されていることがわかりました(少なくとも、AjaxBehaviorRenderer.decode(FacesContextコンテキスト、UIComponentコンポーネント、ClientBehaviorの動作)のメソッドでは、イベントオブジェクトは存在し、nullではありません)。
3、およびJlltWssbDjjsbEditPage.setSelectedMarker(OverlaySelectEvent event)のメソッドでは、イベントはnullです。
みんなありがとう!
はっきりさせておきたいと思います。