以前說了JFreechart的基本使用方法,包括生成餅圖、柱狀統計圖和折線統計圖的方法。如今須要將其整合到數據採集系統中根據調查結果生成三種不一樣的統計圖。css
實現統計圖顯示的流程:單擊導航欄中的「個人調查」超連接->在調查列表中單擊指定的調查中的「分析」超連接->統計Action獲取請求參數(questionId)並根據該值計算統計圖所須要的全部參數,生成統計圖,並將統計圖以流的形式返回到前端顯示。爲了簡單起見,這裏直接在瀏覽器新開了一個窗口顯示統計圖,並無進行彈窗顯示。前端
統計圖須要的數據主要有:sql
1.當前問題有多少人回答數據庫
2.該問題的每一個選項有多少人回答apache
這兩種數據是實現統計圖所須要的全部數據。編程
那麼根據需求能夠獲得須要的實體有「選項」、「問題」兩個,其中,問題實體已經在前面有過定義,那麼還須要從新定義一個嗎?實際上咱們還須要從新定義一個問題實體,由於若是貿然給問題實體添加一個count屬性,於理不合;不只如此還須要給問題添加一個「選項列表」的字段,更是不知所謂。通過分析,設計的另外一個問題實體數據結構以下:數組
給它設計三個字段,名爲QuestionStatisicModel:瀏覽器
//對應的那個問題 private Question question; //回答的人數 private int count; //問題中每一個選項的統計狀況 private List<OptionStatisticModel> osms=new ArrayList<OptionStatisticModel>();//這個直接初始化的時候賦值,方便之後調用
接着是選項實體,選項實體的設計比較複雜,這裏的選項必須可以表示九種類型的全部選項類型,而且不只僅須要保存選項的內容,還須要保存與之對應的索引值,咱們採集完成以後保存到數據庫中的都是答案的索引值。網絡
針對就九州九種類型的題型,現設計以下的數據結構,名爲OptionStatisticModel:數據結構
1 //選項標籤 2 private String optionLabel; 3 //選項的索引值 4 private int optionIndex; 5 //矩陣型的行標籤 6 private String matrixRowLabel; 7 //矩陣型的航標籤的索引值 8 private int matirxRowIndex; 9 //矩陣型的列標籤 10 private String matrixColLabel; 11 //矩陣型問題的列標籤的索引值 12 private int matrixColIndex; 13 //矩陣型下拉列表標籤 14 private String matrixSelectLabel; 15 //矩陣型下拉列表標籤的索引值 16 private int matrixSelectIndex; 17 //該選項有多少人選擇 18 private int count;
因爲這兩個不保存到數據庫,因此使用其餘包存放這兩個類:com.kdyzm.domain.statistic
咱們須要一個方法,輸入參數是Question對象,輸出參數是QestionStatisticModel,咱們只要獲得了QuestionStaticsticModel對象就至關於拿到了統計圖須要的全部數據。
每一個答案都有questionId來標識,咱們只須要統計出在答案表中有多少個questionid和指定的questionid相同便可。
String hql="select count(*) from Answer a where questionId=?"; int qcount=answerDao.getQuestionResponseCount(hql,question.getQuestionId());
選項統計是比較複雜的,這裏將非矩陣式問題和矩陣式問題分別處理,同時針對問題6(文本框類型的問題)這種類型的就不作統計了。
統計選項問題的核心是使用sql中的模糊查找功能,即like關鍵字,爲了更加方便的使用這一點,須要在數據庫中的答案字符串兩端加上',',不須要修改數據庫,直接使用字符串鏈接方法便可:
select count(*) from Answer a where a.questionId=? and concat(',',a.answerIndexs,',') like ?
?是佔位符,以後使用Question中的每一個選項的索引值填充,便可統計出每一個選項的被選中的個數。
1 String []optionArr=question.getOptionTextArr(); 2 OptionStatisticModel optionStatisticModel=null; 3 for(int i=0;i<optionArr.length;i++){ 4 String option=optionArr[i]; 5 //這裏i就是索引值,而opiton就是標籤 6 optionStatisticModel=new OptionStatisticModel(); 7 optionStatisticModel.setOptionLabel(option); 8 optionStatisticModel.setOptionIndex(i); 9 ocount=answerDao.getOptionResponseAmount(hql,question.getQuestionId(),"%,"+i+",%"); 10 optionStatisticModel.setCount(ocount); 11 options.add(optionStatisticModel); 12 } 13 //這裏還須要考慮到有其它選項的狀況 14 if(question.isOther()){ 15 //option就是標籤 16 String option="other"; 17 optionStatisticModel=new OptionStatisticModel(); 18 optionStatisticModel.setOptionLabel(option); 19 ocount=answerDao.getOptionResponseAmount(hql,question.getQuestionId(),"%other%"); 20 optionStatisticModel.setCount(ocount); 21 options.add(optionStatisticModel); 22 } 23 break;
注意%通配符的使用。
矩陣式問題處理方式相似,只不過須要進行循環的嵌套而已,須要兩重循環(矩陣式單選框問題或者矩陣式複選框類型)或者三重循環(矩陣式下拉列表選項)。
1 String []rows=question.getMatrixRowTitleArr(); 2 String []cols=question.getMatrixColTitleArr(); 3 String []selectOptionArr=question.getMatrixSelectOptionArr(); 4 //這裏至少須要兩重循環,最多須要三重循環(是下拉列表框的類型) 5 for(int i=0;i<rows.length;i++){ 6 for(int j=0;j<cols.length;j++){ 7 //這裏分爲兩種狀況,一種狀況是radio/checkbox的類型,一種狀況是select類型 8 9 //radio/checkbox類型的 10 if(question.getQuestionType()<8){ 11 optionStatisticModel=new OptionStatisticModel(); 12 optionStatisticModel.setMatirxRowIndex(i); 13 optionStatisticModel.setMatrixColLabel(rows[i]); 14 optionStatisticModel.setMatrixColIndex(j); 15 optionStatisticModel.setMatrixColLabel(cols[j]); 16 17 ocount=answerDao.getOptionResponseAmount(hql, question.getQuestionId(), "%,"+i+"_"+j+",%"); 18 optionStatisticModel.setCount(ocount); 19 options.add(optionStatisticModel); 20 } 21 //select類型的 22 if(question.getQuestionType()==8){ 23 for(int k=0;k<selectOptionArr.length;k++){ 24 if(i==0&&j==0&&k==1){ 25 System.out.println("繼續檢測"); 26 } 27 optionStatisticModel=new OptionStatisticModel(); 28 optionStatisticModel.setMatirxRowIndex(i); 29 optionStatisticModel.setMatrixColLabel(rows[i]); 30 optionStatisticModel.setMatrixColIndex(j); 31 optionStatisticModel.setMatrixColLabel(cols[j]); 32 optionStatisticModel.setMatrixSelectIndex(k); 33 optionStatisticModel.setMatrixSelectLabel(selectOptionArr[k]); 34 35 ocount=answerDao.getOptionResponseAmount(hql, question.getQuestionId(), "%,"+i+"_"+j+"_"+k+",%"); 36 optionStatisticModel.setCount(ocount); 37 options.add(optionStatisticModel); 38 } 39 } 40 } 41 }
1 public QuestionStatisticModel statics(Question question){ 2 System.out.println("訪問了QuestionStatisticService的statics方法"); 3 4 5 /*question.setTitle("測試事務"); 6 questionDao.updateEntity(question);*/ 7 8 //該方法邏輯上分析是加上了事務的,可是須要進行測試是否真正加上了事務。 9 QuestionStatisticModel questionStatisticModel=new QuestionStatisticModel(); 10 11 //設置Question對象 12 questionStatisticModel.setQuestion(question); 13 14 //獲取問題回答人數 15 String hql="select count(*) from Answer a where questionId=?"; 16 int qcount=answerDao.getQuestionResponseCount(hql,question.getQuestionId()); 17 questionStatisticModel.setCount(qcount); 18 19 //最重要的一個問題就是獲取每一個選項的統計問題,即填充List<OptionStatisticsModel>列表 20 List<OptionStatisticModel>options=questionStatisticModel.getOsms(); 21 22 int questionType=question.getQuestionType(); 23 //使用到的hql語句都只是同一個 24 hql="select count(*) from Answer a where a.questionId=? and concat(',',a.answerIndexs,',') like ?"; 25 //每一個選項的統計數據初始化爲0 26 int ocount=0; 27 switch(questionType){ 28 case 0: 29 case 1: 30 case 2: 31 case 3: 32 case 4: 33 String []optionArr=question.getOptionTextArr(); 34 OptionStatisticModel optionStatisticModel=null; 35 for(int i=0;i<optionArr.length;i++){ 36 String option=optionArr[i]; 37 //這裏i就是索引值,而opiton就是標籤 38 optionStatisticModel=new OptionStatisticModel(); 39 optionStatisticModel.setOptionLabel(option); 40 optionStatisticModel.setOptionIndex(i); 41 ocount=answerDao.getOptionResponseAmount(hql,question.getQuestionId(),"%,"+i+",%"); 42 optionStatisticModel.setCount(ocount); 43 options.add(optionStatisticModel); 44 } 45 //這裏還須要考慮到有其它選項的狀況 46 if(question.isOther()){ 47 //option就是標籤 48 String option="other"; 49 optionStatisticModel=new OptionStatisticModel(); 50 optionStatisticModel.setOptionLabel(option); 51 ocount=answerDao.getOptionResponseAmount(hql,question.getQuestionId(),"%other%"); 52 optionStatisticModel.setCount(ocount); 53 options.add(optionStatisticModel); 54 } 55 break; 56 /* 57 * 類型5是文本框類型,不作統計 58 * */ 59 case 6: 60 case 7: 61 case 8: 62 String []rows=question.getMatrixRowTitleArr(); 63 String []cols=question.getMatrixColTitleArr(); 64 String []selectOptionArr=question.getMatrixSelectOptionArr(); 65 //這裏至少須要兩重循環,最多須要三重循環(是下拉列表框的類型) 66 for(int i=0;i<rows.length;i++){ 67 for(int j=0;j<cols.length;j++){ 68 //這裏分爲兩種狀況,一種狀況是radio/checkbox的類型,一種狀況是select類型 69 70 //radio/checkbox類型的 71 if(question.getQuestionType()<8){ 72 optionStatisticModel=new OptionStatisticModel(); 73 optionStatisticModel.setMatirxRowIndex(i); 74 optionStatisticModel.setMatrixColLabel(rows[i]); 75 optionStatisticModel.setMatrixColIndex(j); 76 optionStatisticModel.setMatrixColLabel(cols[j]); 77 78 ocount=answerDao.getOptionResponseAmount(hql, question.getQuestionId(), "%,"+i+"_"+j+",%"); 79 optionStatisticModel.setCount(ocount); 80 options.add(optionStatisticModel); 81 } 82 //select類型的 83 if(question.getQuestionType()==8){ 84 for(int k=0;k<selectOptionArr.length;k++){ 85 if(i==0&&j==0&&k==1){ 86 System.out.println("繼續檢測"); 87 } 88 optionStatisticModel=new OptionStatisticModel(); 89 optionStatisticModel.setMatirxRowIndex(i); 90 optionStatisticModel.setMatrixColLabel(rows[i]); 91 optionStatisticModel.setMatrixColIndex(j); 92 optionStatisticModel.setMatrixColLabel(cols[j]); 93 optionStatisticModel.setMatrixSelectIndex(k); 94 optionStatisticModel.setMatrixSelectLabel(selectOptionArr[k]); 95 96 ocount=answerDao.getOptionResponseAmount(hql, question.getQuestionId(), "%,"+i+"_"+j+"_"+k+",%"); 97 optionStatisticModel.setCount(ocount); 98 options.add(optionStatisticModel); 99 } 100 } 101 } 102 } 103 break; 104 default:break; 105 } 106 return questionStatisticModel; 107 }
必須將全部調查的全部頁面的全部問題都顯示出來。針對不一樣類型的問題有不一樣的提示,好比針對前5種類型的問題,咱們須要給出查看各類統計圖的按鈕;若是是文本框類型,則直接給出「不可統計」的提示;若是是矩陣類型的問題,則使用普通的餅狀圖、直方圖或者折線圖都不能表示出來了,咱們直接給出「查看矩陣類型統計圖」的按鈕,綜合分析以後,設計的核心代碼以下:
1 <s:iterator value="%{#page.questions}" var="question" status="qst"> 2 <tr> 3 <s:if test="#qst.index==0"> 4 <td width="15px" rowspan='<s:property value="%{#page.questions.size()}"/>'></td> 5 </s:if> 6 <td align="left"> 7 <s:property value="#qst.count+'.'+#question.title"/> 8 <div style="display:inline-block;float: right;margin-right: 10px;width: 30%;"> 9 <s:if test="#question.questionType==5"> 10 不可統計 11 </s:if> 12 <s:elseif test="#question.questionType>=6"> 13 <s:form action="StatisticAction_statisticMatrix.action" namespace="/"> 14 <s:hidden name="questionId"> 15 <s:property value="%{#question.questionId}"/> 16 </s:hidden> 17 <s:submit value="查看矩陣式統計圖"/> 18 </s:form> 19 </s:elseif> 20 <s:else> 21 <s:form action="StatisticAction_statistic.action" namespace="/"> 22 <s:hidden name="questionId"> 23 <s:property value="%{#question.questionId}"/> 24 </s:hidden> 25 <s:select name="statisticType" cssStyle="width:150px;border:1px solid gray;text-align:center;" list="#{0:'平面餅圖',1:'立體餅圖',2:'橫向平面柱狀圖',3:'縱向平面柱狀圖',4:'橫向立體柱狀圖',5:'縱向立體柱狀圖',6:'平面折線圖',7:'立體折線圖'}"></s:select> 26 <s:submit value="查看統計圖"/> 27 </s:form> 28 </s:else> 29 </div> 30 </td> 31 </tr> 32 </s:iterator>
運行界面以下:
Action中的統計方法肩負着「承上啓下」的重任,它須要接收前端的請求,還須要調用Service方法,最後整理好再返回到前端。由以前的前端代碼能夠看出來,我是用了兩種方法對矩陣型的問題和非矩陣類型的問題分別加以對待。
實際上咱們不須要JFreechart插件就可以實現,無非是將流寫入到前端,可是不推薦這麼作,究其緣由仍是效率的問題。若是咱們本身寫,大概咱們會這麼幹:首先在Action中頂一個輸入流,而後提供set/get方法,在統計方法中經過chart得到輸入流,可使用ByteArrayOutputStream接收chart的輸出,而後讀到ByteArrayInputStream,而後賦值給Action中的InputStream類型的變量。最後,經過配置文件配置一下便可:
<result name="success" type="stream"> <param name="contentType">image/jpeg</param> <param name="inputName">is</param> <param name="bufferSize">1024</param> </result>
這實際上通過了一個「流結果集類型」(org.apache.struts2.dispatcher.StreamResult)進行了處理,該結果集作的事情只是從流中將數據取出而後寫出到網絡輸出流中。而後咱們回顧整個流程:chart->輸出流->輸入流->輸出流,好吧,爲何不直接寫出到網絡輸出流呢?所以struts2提供了一個插件專門用於解決這個問題,它解決該問題的方案就是直接將數據寫入網絡輸出流中,在struts2依賴包下就可以找到該jar包:struts2-jfreechart-plugin-2.3.1.2.jar
接着咱們須要幹兩件事:
第一,在Action中配置變量名稱爲chart的JFreeChart類型的變量並提供set/get方法。
經過查看源代碼,咱們能夠發現插件中的類默認讀取的名字就是chart,若是不想使用該名字就須要到strus2配置文件中重寫定義覆蓋原來的定義。
第二,配置struts2配置文件
<result name="success" type="chart"> <param name="value">chart</param> <param name="type">png</param> <param name="width">800</param> <param name="height">480</param> </result>
結果集類型變成chart,同時爲了保險起見,將Action中的名字也寫一下。
1 public String statistic() throws Exception { 2 chart = null; 3 /** 4 * 在統計以前先綁定數據 5 */ 6 System.out.println("訪問了StatisticAction的statistic方法!"); 7 Question question=questionService.getQuestion(questionId); 8 Survey survey=question.getPage().getSurvey(); 9 SurveyToken surveyToken=new SurveyToken(); 10 surveyToken.setSurvey(survey); 11 SurveyToken.bind(surveyToken); 12 System.out.println("即將訪問statisticService的統計方法!"); 13 QuestionStatisticModel questionStatisticModel = this.statisticService.statics(question); 14 //解除綁定,實際上已經解除綁定過一次了可是好像並無論用 15 SurveyToken.unbind(); 16 DefaultPieDataset pieDataset = null; 17 DefaultCategoryDataset categoryDataset = null; 18 try { 19 if (statisticType < 2) {// 餅圖 20 pieDataset = new DefaultPieDataset(); 21 for (OptionStatisticModel option : questionStatisticModel.getOsms()) { 22 pieDataset.setValue(option.getOptionLabel(), option.getCount()); 23 } 24 } else { // 其它 25 categoryDataset = new DefaultCategoryDataset(); 26 for (OptionStatisticModel option : questionStatisticModel.getOsms()) { 27 categoryDataset.setValue(option.getCount(), option.getOptionLabel(), "第一季度"); 28 } 29 } 30 switch (this.statisticType) { 31 case 0: 32 // 平面餅圖 33 chart = ChartFactory.createPieChart(questionStatisticModel.getQuestion().getTitle(), pieDataset, true, 34 false, false); 35 ((PiePlot)chart.getPlot()).setLabelGenerator(new StandardPieSectionLabelGenerator("{0}/{1}/{2}/{3}")); 36 break; 37 case 1: 38 // 立體餅圖 39 chart = ChartFactory.createPieChart3D(questionStatisticModel.getQuestion().getTitle(), pieDataset, true, 40 true, true); 41 chart.getPlot().setForegroundAlpha(0.7F); // 設置透明度 42 ((PiePlot)chart.getPlot()).setLabelGenerator(new StandardPieSectionLabelGenerator("{0}/{1}/{2}/{3}")); 43 break; 44 case 2: 45 // 橫向平面柱狀圖 46 chart = ChartFactory.createBarChart(questionStatisticModel.getQuestion().getTitle(), "", "", 47 categoryDataset, PlotOrientation.HORIZONTAL, true, true, true); 48 break; 49 case 3: 50 // 縱向平面柱狀圖 51 chart = ChartFactory.createBarChart(questionStatisticModel.getQuestion().getTitle(), "", "", 52 categoryDataset, PlotOrientation.VERTICAL, true, true, true); 53 break; 54 case 4: 55 chart = ChartFactory.createBarChart3D(questionStatisticModel.getQuestion().getTitle(), "", "", 56 categoryDataset, PlotOrientation.HORIZONTAL, true, true, true); 57 break; 58 // 橫向立體柱狀圖 59 case 5: 60 chart = ChartFactory.createBarChart3D(questionStatisticModel.getQuestion().getTitle(), "", "", 61 categoryDataset, PlotOrientation.VERTICAL, true, true, true); 62 break; 63 // 縱向立體柱狀圖 64 case 6: 65 /** 66 * 折線圖的生成發生了問題 67 * TODO 這裏的折線圖若是都是同一個組中的,那麼就不會顯示折線圖了 68 * 必須至少有兩個組才行 69 */ 70 chart = ChartFactory.createLineChart(questionStatisticModel.getQuestion().getTitle(), "", "", 71 categoryDataset, PlotOrientation.VERTICAL, true, false, false); 72 break; 73 // 平面折線圖 74 case 7: 75 // 立體折線圖 break; default: 76 chart = ChartFactory.createLineChart3D(questionStatisticModel.getQuestion().getTitle(), "", "", 77 categoryDataset, PlotOrientation.VERTICAL, true, false, false); 78 break; 79 } 80 // 集中解決中文亂碼問題 81 chart.getTitle().setFont(new Font("宋體", Font.BOLD, 30)); 82 chart.getLegend().setItemFont(new Font("宋體", Font.PLAIN, 16)); 83 if (chart.getPlot() instanceof PiePlot) { 84 PiePlot piePlot = (PiePlot) chart.getPlot(); 85 piePlot.setLabelFont(new Font("宋體", Font.PLAIN, 20)); 86 } else { 87 Font font = new Font("宋體", Font.PLAIN, 15); 88 chart.getCategoryPlot().getDomainAxis().setLabelFont(font); 89 chart.getCategoryPlot().getDomainAxis().setTickLabelFont(font); 90 chart.getCategoryPlot().getRangeAxis().setLabelFont(font); 91 chart.getCategoryPlot().getRangeAxis().setTickLabelFont(font); 92 chart.getPlot().setForegroundAlpha(0.7F); 93 } 94 } catch (Exception e) { 95 e.printStackTrace(); 96 } 97 System.out.println("StatisticAction的統計方法結束"); 98 return SUCCESS; 99 }
須要注意的是使用折線圖統計的結果是沒有的,在這裏也只是空有名頭而已,倒不是程序有問題,這是折線圖自己所的特性決定的;上述粗體部分是餅圖和直方圖的不一樣之處。
提供了集中幾種選項供選擇:
餅狀圖
直方圖:
折線統計圖不適合在這裏作,雖然作了,可是沒有效果,略。
矩陣式問題統計沒有辦法使用JFreechart生成統計圖(其實是不會,JFreechart這種逆天的統計類庫什麼樣的統計圖都可以給你搞出來),因此使用自定義的統計圖來實現統計,因此好像要簡單了好多,統計方法:
1 // 矩陣式問題統計圖 2 public String statisticMatrix() throws Exception { 3 question=this.questionService.getQuestion(this.questionId); 4 questionStatisticModel=this.statisticService.statics(question); 5 ActionContext.getContext().getValueStack().push(questionStatisticModel); 6 ActionContext.getContext().put("colors", colors); 7 return ""+question.getQuestionType(); 8 }
而後配置文件將其轉發到不一樣的頁面進行顯示
<!-- 接收不一樣種類消息,轉發到不一樣的頁面 --> <result name="6">/statistic/nomalMatrixStatistic.jsp</result> <result name="7">/statistic/nomalMatrixStatistic.jsp</result> <result name="8">/statistic/selectMatrixStatistic.jsp</result>
能夠看出來,矩陣式單選框問題和矩陣式複選框問題使用同一個界面;矩陣式下拉列表類型的問題使用另一個界面。
1 <table> 2 <tr> 3 <td colspan='<s:property value="%{osms.size+1}"/>'> 4 <s:property value="%{question.title}"/> 5 </td> 6 </tr> 7 <!-- 首先遍歷行標籤 --> 8 <tr> 9 <td> </td> 10 <s:iterator value="%{question.matrixColTitleArr}"> 11 <td align="center"> 12 <s:property/> 13 </td> 14 </s:iterator> 15 </tr> 16 <s:iterator value="%{question.matrixRowTitleArr}" var="row" status="rst"> 17 <tr> 18 <td align="center"> 19 <s:property/><--列標籤--> 20 </td> 21 <s:iterator value="%{question.matrixColTitleArr}" var="col" status="cst"> 22 <td align="center"> 23 <s:property value="getPercent(#rst.index,#cst.index)"/> 24 </td> 25 </s:iterator> 26 </tr> 27 </s:iterator> 28 <tr> 29 <td colspan='<s:property value="%{osms.size+1}"/>'> 30 一共有 <s:property value="%{count}"/> 人蔘與了問卷! 31 </td> 32 </tr> 33 </table>
這裏使用了一個很是重要的方法進行數據的顯示統計。getPercent(rowIndex,columnIndex)。
1 public String getPercent(int row,int col) throws Exception{ 2 int qcount=this.questionStatisticModel.getCount(); 3 int ocount=0; 4 for(OptionStatisticModel osm:this.questionStatisticModel.getOsms()){ 5 if(osm.getMatirxRowIndex()==row&&osm.getMatrixColIndex()==col){ 6 ocount=osm.getCount(); 7 break; 8 } 9 } 10 double result=(double)ocount/(double)qcount; 11 result=result*100; 12 DecimalFormat format=new DecimalFormat("#,###.00"); 13 return ""+ocount+"{"+format.format(result)+"%}"; 14 }
該方法就是遍歷全部選項並獲取選擇該項的人數/總數,注意這裏直接使用QuestionStatisticModel對象是沒有問題的。
最終效果圖:
這種類型的問題統計相對來講就比較複雜了。由於這裏的每一個選項都是下拉列表。可是處理過程無非是從(1)中的2中判斷編程3種判斷而已。關鍵是頁面的顯示比較複雜。咱們使用條形的文本框長度來表示百分比。不一樣顏色的文本框表明不一樣的下拉列表選型。效果以下圖所示:
首先,前端標籤是第一步須要設計解決的:
1 <table> 2 <tr> 3 <td colspan='<s:property value="%{osms.size+1}"/>'> 4 <s:property value="%{question.title}"/> 5 </td> 6 </tr> 7 <tr> 8 <td colspan='<s:property value="%{osms.size+1}"/>'> 9 10 <s:iterator value="%{question.matrixSelectOptionArr}" status="st"> 11 <input readonly="readonly" style="width: 10px;height: 10px;background-color: <s:property value='%{#colors[#st.index]}'/>"> 12 <s:property/> 13 </s:iterator> 14 </td> 15 </tr> 16 <!-- 首先遍歷表頭 --> 17 <tr> 18 <td> </td> 19 <s:iterator value="%{question.matrixColTitleArr}"> 20 <td align="center"> 21 <s:property/> 22 </td> 23 </s:iterator> 24 </tr> 25 <s:iterator value="%{question.matrixRowTitleArr}" var="row" status="rst"> 26 <tr> 27 <td align="center"> 28 <s:property/> 29 </td> 30 <s:iterator value="%{question.matrixColTitleArr}" var="col" status="cst"> 31 <td align="center"> 32 <s:iterator value="%{question.matrixSelectOptionArr}" var="op" status="ost"> 33 <input style="height:10px;float:left;background-color: <s:property value='%{colors[#ost.index]}'/>;width:<s:property value="getWidth(#rst.index,#cst.index,#ost.index)"/>px;" readonly="readonly"/> 34 <span style="font-size:12px;float:right;display: inline-block;text-align: right;"><s:property value="getPercent(#rst.index,#cst.index,#ost.index)"/></span> 35 <br/> 36 </s:iterator> 37 </td> 38 </s:iterator> 39 </tr> 40 </s:iterator> 41 <tr> 42 <td colspan='<s:property value="%{osms.size+1}"/>'> 43 一共有 <s:property value="%{count}"/> 人蔘與了問卷! 44 </td> 45 </tr> 46 </table>
在這個頁面中使用到了兩個方法:getPercent(rowIndex,columnIndex,optionIndex)和getWidth(rowIndex,columnIndex,optionIndex),其中前者是重載方法,它有三個參數,以前咱們使用的方法是兩個參數。
getPercent方法是獲取百分比的,二getWidth方法是獲取文本框長度的。
getPercent方法:
1 public String getPercent(int row,int col,int op) throws Exception{ 2 int qcount=this.questionStatisticModel.getCount(); 3 int ocount=0; 4 for(OptionStatisticModel osm:this.questionStatisticModel.getOsms()){ 5 if(osm.getMatirxRowIndex()==row&&osm.getMatrixColIndex()==col&&osm.getMatrixSelectIndex()==op){ 6 ocount=osm.getCount(); 7 break; 8 } 9 } 10 double result=(double)ocount/(double)qcount; 11 result=result*100; 12 DecimalFormat format=new DecimalFormat("#,###.00"); 13 return ""+ocount+"("+format.format(result)+"%)"; 14 }
getWidth方法:獲取百分比以後X100*2做爲文本框的長度正合適。
1 public String getWidth(int row,int col,int op) throws Exception{ 2 int qcount=this.questionStatisticModel.getCount(); 3 int ocount=0; 4 for(OptionStatisticModel osm:this.questionStatisticModel.getOsms()){ 5 if(osm.getMatirxRowIndex()==row&&osm.getMatrixColIndex()==col&&osm.getMatrixSelectIndex()==op){ 6 ocount=osm.getCount(); 7 break; 8 } 9 } 10 double result=(double)ocount/(double)qcount; 11 result=result*100; 12 return (int)result*2+""; 13 }
最後一個問題就是顏色的選取問題,我在Action中定義了一個顏色數組,而且提供了get/set方法,這樣在前端就可以直接使用了,文本框的顏色直接使用其option的索引值所在的顏色字符串。
1 String colors[]={ 2 "aqua", 3 "black", 4 "blue", 5 "fuchsia", 6 "fuchsia", 7 "gray", 8 "green", 9 "lime", 10 "maroon", 11 "navy", 12 "olive", 13 "orange", 14 }; 15 public String[] getColors() { 16 return colors; 17 } 18 public void setColors(String[] colors) { 19 this.colors = colors; 20 }