一、序
最近公司做的項目里出現了一個新的需求,項目大部分是為金融業定制開發的數據集成平台,包括數據的采集,處理,使用。
數據的采集方式不固定,有機構化數據,有非結構話數據,還有附件等其它文件形式。
對於采集端,大部分要求具備硬件服務器架設能力,這時就出現了一個問題,有些采集端是不具備硬件服務器架設能力的,或者主觀上不願意架設,
要求公司拿出一套可以不假設服務器,而是和中心服務器交互。
功能精簡為:只保留數據采集,數據結果由中心服務器來提供,客戶端安裝模式。
二、解決:
我們是JAVA,要開發客戶端,那就是AWT、SWING,業內也一直都說是C#更適合開發。
老板一句話,兩周之內要產品,沒辦法,還是用熟悉的SWING吧。遇到了很多問題,中間很坎坷,在這里記錄一下:
(1)頁面的設計嵌套時,要整個包裹好再放入另一個容器里,這樣就可以保證樣式
(2)SWING時間控件的選擇很少,第三方的時間控件又很難滿足具體項目的定制需求
(3)表格的分頁,表格單元格顯示復選框的感覺很別扭
三、重點:
(1)框架居中:
//第一種居中方式(為空時默認居中) this.setLocationRelativeTo(null); //第二種居中方式(獲取屏幕來居中) int width = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int height = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight(); this.setBounds((int)(width/2-500/2), (int)(height/2-350/2), 500, 350); //this.setUndecorated(true); this.setResizable(false);(2)分割框的分割比重
//第一種設置方式,不具有強制性,有可能設置失敗 panel_split.setResizeWeight(0.6); //第二種設置方式,可以指定分割框所占的比重 panel_split.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { panel_split.setDividerLocation(1.0 / 4.0); } }); panel_split.setOrientation(JSplitPane.VERTICAL_SPLIT);(3)表格插入圖片的時候顯示字符串
//其中6、7均為格式需要轉換為圖片的列位置 table = new JTable(model){ @SuppressWarnings({ "unchecked", "rawtypes" }) public Class getColumnClass(int column) { if (column==6 && model.getDataVector().size()>0) { return getValueAt(0, 6).getClass(); } else if(column==7 && model.getDataVector().size()>0) { return getValueAt(0, 7).getClass(); } else { return getValueAt(0, 0).getClass(); } } }; //圖片數據列的插入 row.addElement(new ImageIcon(this.getClass().getClassLoader().getResource("reload.png"))); //普通字串數據列的插入 row.add(data.get("FILE_ID")==null?new String(""):data.get("FILE_ID"));(4)分頁對象
//分頁對象 package com.dis.view; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; @SuppressWarnings("serial") public abstract class SubPageBar extends JPanel implements ItemListener, ActionListener { private int allCount, fromRec, endRec, pageSize, pageIndex, pageCount; private JLabel allCountLab, curCountLab, pageIndexLab; @SuppressWarnings("rawtypes") private JComboBox eachCom; // 首頁 private JButton firstPageButton; // 前一頁 private JButton latePageButton; // 下一頁 private JButton nextPageButton; // 末頁 private JButton lastPageButton; public SubPageBar(int recNums) { this.allCount = recNums; initUI(); updateData(); } @SuppressWarnings({ "unchecked", "rawtypes" }) private void initUI() { // comboBox eachCom = new JComboBox(new String[] { "10", "20", "50" }); // label curCountLab = new JLabel(); allCountLab = new JLabel(); pageIndexLab = new JLabel(); // button firstPageButton = new JButton("首頁"); latePageButton = new JButton("上一頁"); nextPageButton = new JButton("下一頁"); lastPageButton = new JButton("末頁"); // listener eachCom.addItemListener(this); firstPageButton.addActionListener(this); nextPageButton.addActionListener(this); latePageButton.addActionListener(this); lastPageButton.addActionListener(this); this.setLayout(new FlowLayout(FlowLayout.RIGHT)); this.add(curCountLab); this.add(allCountLab); this.add(new JLabel("每頁")); this.add(eachCom); this.add(new JLabel("條")); this.add(firstPageButton); this.add(latePageButton); this.add(pageIndexLab); this.add(nextPageButton); this.add(lastPageButton); } /** * @Description: (更新分頁欄的值) */ private void updateData() { // 必須知道的參數值:allCount pageIndex pageSize pageSize = Integer.valueOf(eachCom.getSelectedItem().toString()); fromRec = pageIndex * pageSize + 1; if (0 == allCount) { fromRec = 0; } endRec = (pageIndex + 1) * pageSize; if (endRec > allCount) { endRec = allCount; } pageSize = (0 == pageSize) ? 1 : pageSize; pageCount = allCount / pageSize - ((0 == allCount % pageSize && 0 != allCount) ? 1 : 0); // curCountLab.setText("第 " + fromRec + "~" + endRec + " 條"); allCountLab.setText("【共有 " + allCount + " 條】 "); pageIndexLab.setText(" 【第 " + (pageIndex) + "/" + (pageCount + 1) + " 頁】 "); firstPageButton.setEnabled(pageIndex > 0); latePageButton.setEnabled(pageCount > 0 && pageIndex > 0); nextPageButton.setEnabled(pageIndex < pageCount); lastPageButton.setEnabled(pageCount > 0 && pageIndex < pageCount); } /** * @Description: 有新數據載入時,需要重載 */ public void fresh(int recNums) { this.allCount = recNums; updateData(); } @Override public void itemStateChanged(ItemEvent e) { // 這邊之所以要加上這個判斷,是因為“選中”和“取消選中”都會觸發ItemEvent. if (e.getStateChange() == ItemEvent.SELECTED) { pageIndex = 0; pageSize = Integer.valueOf(eachCom.getSelectedItem().toString()); updateData(); onPageSizeChange(pageSize); } } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == firstPageButton) { pageIndex = 1; onClickPreButton(pageIndex); } else if (e.getSource() == latePageButton) { pageIndex--; onClickPreButton(pageIndex); } else if (e.getSource() == nextPageButton) { pageIndex++; onClickNextButton(pageIndex); } else if (e.getSource() == lastPageButton) { pageIndex = pageCount; onClickNextButton(pageIndex); } updateData(); } public int getPageIndex() { return (pageIndex>0) ? pageIndex : 1; } public void updatePageIndex(int pageIndex) { this.pageIndex = pageIndex; updateData(); } public int getPageSize() { return pageSize; } public abstract void onPageSizeChange(int newPageSize); public abstract void onClickPreButton(int pageIndex); public abstract void onClickNextButton(int pageIndex); } //分頁對象集成 table_col_name = new Vector<>(); table_col_name.add("編號"); table_col_name.add("文件名"); table_col_name.add("機構名"); table_col_name.add("流程名"); table_col_name.add("當前狀態"); table_col_name.add("變更時間"); table_col_name.add("操作"); table_col_name.add("重置"); Vector<Vector<Object>> rowData = new Vector<Vector<Object>>(); DefaultTableModel model = new DefaultTableModel(rowData, table_col_name); table = new JTable(model){ @SuppressWarnings({ "unchecked", "rawtypes" }) public Class getColumnClass(int column) { if (column==6 && model.getDataVector().size()>0) { return getValueAt(0, 6).getClass(); } else if(column==7 && model.getDataVector().size()>0) { return getValueAt(0, 7).getClass(); } else { return getValueAt(0, 0).getClass(); } } }; table.getTableHeader().setReorderingAllowed(false);// 限制整列拖動 table.setEnabled(false); table.addMouseListener(tableListener); table_bar = new SubPageBar(0) { @Override public void onPageSizeChange(int newPageSize) { initTable(); } @Override public void onClickPreButton(int pageIndex) { this.updatePageIndex(pageIndex--); initTable(); } @Override public void onClickNextButton(int pageIndex) { this.updatePageIndex(pageIndex++); initTable(); } }; JPanel panel_table = new JPanel(new BorderLayout()); JScrollPane scrollPanel_table = new JScrollPane(); scrollPanel_table.setBorder(border); scrollPanel_table.setViewportView(table); panel_table.add(scrollPanel_table, BorderLayout.CENTER); panel_table.add(table_bar, BorderLayout.SOUTH); scrollPanel_bottom.setViewportView(panel_table); //表格數據加載 //初始化表格 @SuppressWarnings("unchecked") public void initTable() { HashMap<String,String> params = this.getParams(); params.put("page", table_bar.getPageIndex()+""); params.put("rows", table_bar.getPageSize()+""); if (params.get("cycleType")=="-1") { params.remove("cycleType"); } try { //請求數據 // String resultStr = HttpRequest.sendGetRequest(PropertyUtil.readKeyValue(PropertyUtil.CONFIG_FILE_PATH, PropertyUtil.API_GETALLFILE), params,"UTF-8"); String resultStr = HttpRequest.sendGetRequest(Sysconfig.getSysInstance().getProperty(PropertyUtil.API_GETALLFILE), params,"UTF-8"); Page resultPage = GsonUtil.GsonToBean(resultStr, Page.class); //解析數據 int totalCount = resultPage.getTotal(); List<Map<String,String>> fileList = (List<Map<String, String>>) resultPage.getRows(); //渲染表格 table_bar.fresh(totalCount); DefaultTableModel model = (DefaultTableModel) table.getModel(); model.getDataVector().clear(); Vector<Vector<Object>> vData = model.getDataVector(); if(null != fileList && fileList.size() > 0 && totalCount > 0) { Page page = null; page = new Page(totalCount); page.setPageSize(table_bar.getPageSize()); page.setPageNow(pageNow); for (Map<String, String> data : fileList) { Vector<Object> row = new Vector<Object>(); row.add(data.get("FILE_ID")==null?new String(""):data.get("FILE_ID")); row.add(data.get("FILE_NAME")==null?new String(""):data.get("FILE_NAME")); row.add(data.get("BANK_NAME")==null?new String(""):data.get("BANK_NAME")); row.add(data.get("PROCESS_NAME")==null?new String(""):data.get("PROCESS_NAME")); row.add(data.get("NODE_DESC")==null?new String(""):data.get("NODE_DESC")); row.add(data.get("UPDATE_TIME")==null?new String(""): this.parseDate(data.get("UPDATE_TIME"))); row.addElement(new ImageIcon(this.getClass().getClassLoader().getResource("look.png"))); row.addElement(new ImageIcon(this.getClass().getClassLoader().getResource("reload.png"))); row.add(data.get("F_PNODE_STATE")==null?new String(""):data.get("F_PNODE_STATE")); vData.add(row); } } table.getColumnModel().getColumn(7).setCellEditor(new DefaultCellEditor(new JCheckBox())); model.fireTableCellUpdated(0, 7); model.fireTableDataChanged(); } catch (Exception e) { JOptionPane.showMessageDialog(this, "服務地址解析錯誤!"); e.printStackTrace(); log.error("服務地址解析錯誤!"); } }