JRT实现表格元素

数据结构决定算法基础,良好的设计可以极大的减轻上层的复杂度。以前由于受限M没画笔,都得通过Webservice代理出去,所以实现一些效果比较难。用M控制打印绘制表格就很费劲。但是打印报告结果、药敏等很多都是列表排版。用TextLength控制换行或者一个个字符串判断宽度换行实在是实现丑陋。

这些都是需要解决的痛点,先看效果:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

调换画表格代码
在这里插入图片描述

初步画表格实现,画一个表格很复杂,先定义好表格的数据结构,然后基于数据结构实现算法,因为涉及到画行、列、边框、还有单元格换行情况,本次算法上也进行足够的分离,把一个问题分而治之就不那么复杂了,每个方法负责对应职责,差不多一次就写通了。把画表格分割成了画行,画行分割成了画单元格和画构造边框数据,画单元格又分成切割串和画串,最或全部画完了再画边框。

import JRT.Core.DataGrid.GridColDto;
import JRT.Core.DataGrid.GridDto;
import JRT.Core.DataGrid.GridLineDto;
import JRT.Core.DataGrid.GridPageDto;
import JRT.Core.Dto.OutValue;
import JRT.Core.Dto.PrintElement;
import JRT.Core.Metrics.DrawMetricsHandler;
import JRT.Core.Util.PrintDrawProtocol;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;import java.awt.*;
import java.util.*;
import java.util.List;/*** 画表格测试,将要实现一个自动切割和实现换页的表格个业务使用*/
public class DrawGrid extends BaseHttpHandlerNoSession {/*** 按传入的RowID输出符合打印元素绘制协议的数据来实现打印控制** @param RowID   业务主键* @param P1* @param P2* @param P3* @param P4* @param P5* @param P6* @param P7* @param P8* @param P9* @param P10* @param P11* @param P12* @param P13* @param Session* @param Output* @return*/public String GetData(String RowID, String P1, String P2, String P3, String P4, String P5, String P6, String P7, String P8, String P9, String P10, String P11, String P12, String P13, OutValue Session, OutValue Output) throws Exception {List<PrintElement> retList = null;//这部分由设计器维护的Json得到表格维护信息GridDto def = new GridDto();GridPageDto page = new GridPageDto();def.PageList.add(page);GridColDto col = null;//表格列for (int i = 0; i < 5; i++) {col = new GridColDto();col.DataField = "Col" + i;col.Width = 150;def.DataCol.add(col);}//这部分由业务打印组装数据List<Object> dataList = new ArrayList<>();for (int i = 0; i < 15; i++) {GridDataDto one = new GridDataDto();one.Col0 = "第" + i + "行0列,这是比较长的内容额,会自动换行";one.Col1 = "第" + i + "行1列,这是稍微长的内容";one.Col2 = "第" + i + "行2列,this is jrtbase draw grid test for printtemplate";one.Col3 = "第" + i + "行3列";one.Col4 = "1.这是第一行$r$n2.这是第二行$r$n3.这是第三行";dataList.add(one);}OutValue lastYObj = new OutValue();//绘制表格retList = DrawGrid(def, null, dataList, lastYObj);return Helper.Object2Json(retList);}/*** 绘制表格** @param def      表格定义* @param headData 标题数据* @param datas    行数据* @param lastY    绘制完成最后Y* @return 表格的打印绘图元素*/public List<PrintElement> DrawGrid(GridDto def, Object headData, List<Object> datas, OutValue lastY) throws Exception {List<PrintElement> retList = new ArrayList<>();//处理标题字体if (def.HeadCol.size() > 0) {for (GridColDto col : def.HeadCol) {if (col.PrintFont == null) {col.PrintFont = def.PrintFont;}if (col.PrintFontSize == null) {col.PrintFontSize = def.PrintFontSize;}if (col.PrintFontStyle == null) {col.PrintFontStyle = def.PrintFontStyle;}}}//处理数据列字体if (def.DataCol.size() > 0) {for (GridColDto col : def.DataCol) {if (col.PrintFont == null) {col.PrintFont = def.PrintFont;}if (col.PrintFontSize == null) {col.PrintFontSize = def.PrintFontSize;}if (col.PrintFontStyle == null) {col.PrintFontStyle = def.PrintFontStyle;}}}//测量句柄DrawMetricsHandler metricsHandler = new DrawMetricsHandler();//所有的边框HashMap<String, GridLineDto> boderMap = new HashMap();//绘制标题if (headData != null) {}//绘制数据行if (datas != null && datas.size() > 0) {int maxY = def.PageList.get(0).Top;//遍历绘制行for (int i = 0; i < datas.size(); i++) {Object rowData = datas.get(i);//绘制一行数据maxY = DrawOneRow(maxY, i, def, def.DataCol, rowData, boderMap, metricsHandler, retList);}}//画边框for (String key : boderMap.keySet()) {GridLineDto line = boderMap.get(key);PrintElement lineEle = PrintDrawProtocol.DrawLine(line.StartX, line.StartY, line.EndX, line.EndY, def.BoderWidth, "", "");retList.add(lineEle);}return retList;}/*** 绘制一行数据** @param top            顶部* @param rowIndex       行号* @param def            表格定义* @param colList        列定义* @param rowData        一行数据* @param boderMap       边框* @param metricsHandler 测量工具* @param retList        元素* @return 最大Y* @throws Exception*/private int DrawOneRow(int top, int rowIndex, GridDto def, List<GridColDto> colList, Object rowData, HashMap boderMap, DrawMetricsHandler metricsHandler, List<PrintElement> retList) throws Exception {int cellLeft = def.PageList.get(0).Left;int colIndex = -1;//行画到的最大Yint rowMaxY = top + def.RowHeight + def.PaddingTop + def.PaddingBottom;//循环绘制每个单元格内容for (GridColDto col : colList) {colIndex++;//画一个单元格int colMaxY = DrawOneCell(top, cellLeft, def, col, rowData, metricsHandler, retList);if (rowMaxY < colMaxY) {rowMaxY = colMaxY;}cellLeft += col.Width;}colIndex = -1;cellLeft = def.PageList.get(0).Left;//循环组成每个单元格边框for (GridColDto col : colList) {colIndex++;//上边框String key = (rowIndex - 1) + "H#" + colIndex;GridLineDto line = new GridLineDto();line.StartX = cellLeft;line.StartY = top;line.EndX = cellLeft + col.Width;line.EndY = top;boderMap.put(key, line);//下边框key = (rowIndex) + "H#" + colIndex;line = new GridLineDto();line.StartX = cellLeft;line.StartY = rowMaxY;line.EndX = cellLeft + col.Width;line.EndY = rowMaxY;boderMap.put(key, line);//左边框key = (rowIndex) + "V#" + (colIndex - 1);line = new GridLineDto();line.StartX = cellLeft;line.StartY = top;line.EndX = cellLeft;line.EndY = rowMaxY;boderMap.put(key, line);//右边框key = (rowIndex) + "VS#" + (colIndex);line = new GridLineDto();line.StartX = cellLeft + col.Width;line.StartY = top;line.EndX = cellLeft + col.Width;line.EndY = rowMaxY;boderMap.put(key, line);cellLeft += col.Width;}return rowMaxY;}/*** 绘制一个单元格数据** @param top            顶部* @param left           左边* @param def            表格定义* @param col            一列定义* @param rowData        一行数据* @param metricsHandler 测量工具* @param retList        元素* @return 最大Y* @throws Exception*/private int DrawOneCell(int top, int left, GridDto def, GridColDto col, Object rowData, DrawMetricsHandler metricsHandler, List<PrintElement> retList) throws Exception {Object val = JRT.Core.Util.ReflectUtil.GetObjValue(rowData, col.DataField);//画一行时候底部的线坐标int maxY = top + def.RowHeight + def.PaddingTop + def.PaddingBottom;//能画文本的区域宽度int drwAreaWidth = col.Width - def.PaddingLeft + def.PaddingRight;if (val != null) {FontMetrics metrics = metricsHandler.GetFontMetrics(col.PrintFont, col.PrintFontSize, col.PrintFontStyle);String valStr = val.toString();String nr = (char) 13 + "";//替换换行符号valStr = valStr.replace("$r$n", nr);//存多行绘制文本List<String> drawValList = new ArrayList<>();//宽度小于绘制宽度且不包含换行符就直接画if (metrics.stringWidth(valStr) < drwAreaWidth && !valStr.contains(nr)) {drawValList.add(valStr);}//处理换行与宽度计算else {String[] arr = null;//包含换行符if (valStr.contains(nr)) {arr = valStr.split(nr);} else {arr = new String[1];arr[0] = valStr;}//测量切割字符串MetricCutStr(drwAreaWidth, arr, metrics, drawValList);}//绘制一个单元格每行数据if (drawValList.size() > 0) {int startY = top + def.PaddingTop;for (String s : drawValList) {PrintElement lab = PrintDrawProtocol.DrawLabel(left + def.PaddingLeft, startY, s, col.PrintFont, Integer.valueOf(col.PrintFontSize), col.PrintFontStyle, PrintDrawProtocol.GetPrintAlignment(col.PrintAlignment), col.PrintColor, "", "");retList.add(lab);startY += def.RowHeight;}maxY = startY + def.PaddingBottom;}}return maxY;}/*** yyoyon允许宽度和字符测量来切割字符串** @param drwAreaWidth 绘制宽度* @param cutArr       要切割的每行数据* @param metrics      测量工具* @param drawValList  绘图结果行*/private void MetricCutStr(int drwAreaWidth, String[] cutArr, FontMetrics metrics, List<String> drawValList) {//遍历切割多行数据for (String one : cutArr) {if (one.isEmpty()) {drawValList.add("");} else {String cutStr = "";for (int i = 0; i < one.length(); i++) {String c = one.substring(i, i + 1);//换行if (metrics.stringWidth(cutStr + c) > drwAreaWidth - 5) {drawValList.add(cutStr);cutStr = c;} else {cutStr += c;}}if (!cutStr.isEmpty()) {drawValList.add(cutStr);}}}}/*** 数据实体*/public static class GridDataDto {public String Col0;public String Col1;public String Col2;public String Col3;public String Col4;}
}

JRT模板设计实现表格元素基本没阻碍了,稳定的表格将为业务带来简化,得益于框架越来越完善了,写逻辑也可以在业务层先测好再转移到jar包层,实现东西越来越快了,主要只能抽一些带娃间隙,不然速度嗖嗖的,哈哈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321570.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高清网络视频监控平台的应用-城市大交通系统视联网

目 录 一、应用需求 二、系统架构设计 三、功能介绍 1.实时视频监控 2.云台控制 3.语音功能 4. 录像管理与回放 5.告警联动 6.多种显示终端呈现 &#xff08;1&#xff09;CS客户端 &#xff08;2&#xff09;web客户端 &#xff08;3&#xf…

整理的6个Linux运维脚本

整理的6个Linux运维脚本 1、统计/etc/passwd 中能登录的用户&#xff0c;并将对应在/etc/shadow 中第二列密码提取2、查看当前连接到本机的远程IP地址3、检测本机当前用户是否为超级管理员&#xff08;root&#xff09;4、检查指定目录下是否存在对应文件5、查找 Linux 系统中的…

实现线上盲盒购物体验:盲盒商城小程序开发攻略

随着智能手机的普及&#xff0c;移动互联网已经成为人们生活中不可或缺的一部分。在众多的移动应用中&#xff0c;微信小程序以其便捷、简洁的特点备受用户青睐。而在众多的小程序中&#xff0c;盲盒电商小程序正成为下一个爆发点。 盲盒电商是指通过盲盒的形式进行商品销售的一…

设计模式 七大原则

1.单一职责原则 单一职责原则&#xff08;SRP&#xff1a;Single responsibility principle&#xff09;又称单一功能原则 核心&#xff1a;解耦和增强内聚性&#xff08;高内聚&#xff0c;低耦合&#xff09;。 描述&#xff1a; 类被修改的几率很大&#xff0c;因此应该专注…

【TC3xx芯片】TC3xx芯片的GTM模块详解

目录 前言 正文 1.GTM模块功能概述 1.1 GTM具体功能 1.2 GTM架构 2. GTM模块输入时钟 2.1.fGTM的值怎么计算 3. CMU 3.1 CMU功能 3.2 CMU时钟的计算 3..2.1 CLS0_CLK怎么计算 3.2.1 GTM Global Clock时钟计算 3.2.2 分频时钟的计算 4. CCM 4.1 CCM功能 4.2 CCM…

Mysql的四大引擎,账号管理,数据库的建立

数据库存储引擎查看 Support字段说明 default的为默认引擎 YES表示可以使用 NO表示不能使用 命令 SHOW ENGINES 四大引擎 MEMORY 使用场景&#xff1a;由于易失性&#xff0c;可以用于存储在分析中产生的中间表 特点 所有的数据都保存在内存中&#xff0c;一旦服务器重启&…

Spark内核解析-内存管理7(六)

1、Spark内存管理 Spark 作为一个基于内存的分布式计算引擎&#xff0c;其内存管理模块在整个系统中扮演着非常重要的角色。理解 Spark 内存管理的基本原理&#xff0c;有助于更好地开发 Spark 应用程序和进行性能调优。本文中阐述的原理基于 Spark 2.1 版本。 在执行 Spark 的…

ArrayList集合综合练习

文章目录 题目1训练目标训练提示训练步骤参考答案 题目2训练目标训练提示参考方案训练步骤参考答案 题目3训练目标训练提示参考方案训练步骤参考答案 题目4&#xff08;综合&#xff09;训练目标训练提示参考方案训练步骤参考答案 题目1 现有如下字符串元素&#xff1a;[“aaa…

Mysql的基本用法(上)非常详细、快速上手

上篇结束了java基础&#xff0c;本篇主要对Mysql中的一些常用的方法进行了总结&#xff0c;主要对查询方法进行了讲解&#xff0c;包括重要的多表查询用到的内连接和外连接等&#xff0c;以下代码可以直接复制到可视化软件中&#xff0c;方便阅读以及练习&#xff1b; SELECT *…

Microsoft Word去除页面多余的换行符

大家写论文的时候或者排版的时候可能遇到换行符多出来了导致页面的不美观。像下面这张图一样&#xff0c;虽然latex不会出现这种问题。 处理方式 点击插入然后点击分页 结果展示

普通用户用哪款电脑杀毒软件最好?

前言 各位小伙伴接触到电脑的时候&#xff0c;都一定有听过“电脑一定要安装杀毒软件”这句话。 毕竟在电脑诞生之初到今天&#xff0c;电脑木马和病毒依旧存在。 中了木马或病毒的电脑会出现什么现象&#xff1f;具体得看中了什么样的病毒。 但轻则资料泄漏、电脑瘫痪&…

React Admin 前端脚手架之ant-design-pro

文章目录 一、React Admin 前端脚手架选型二、React Admin 前端脚手架之ant-design-pro三、ant-design-pro使用步骤四、常用总结&#xff08;持续更新&#xff09;EditableProTable组件 常用组件EditableProTable组件 编辑某行后&#xff0c;保存时候触发发送请求EditableProTa…