最近用swing做了个工具,实现TXT到PDF的格式转换,其中有个功能是“封面设计器”,当然要求也不是很高,就是可以添加背景图片,可以添加横向和纵向的文本,文本字体可自定义,并且文本位置可拖动定位。
完成思路:
1.封面背景图片重写JPanel的paintComponent方法。
2.封面中文本使用JLabel组件,纵向增加<html>标签<br>换行
3.JLabel组件拖动使用MouseListener中的mouseDragged和mousePressed方法
4.由于swingJPanel中坐标是在左上角视为0,0,而pdf是左下为00,所以需要坐标转换。
5.PDF页面大小和背景图片大小可能不同,所以要以JLabel文本相对于页面的宽高比例去定位PDF的坐标
6.字体转换,swing字体转换为PDF字体,PDF采用加载本地TrueType 字体文件 (.ttf)的形式生成字体
7.PDF用itext生成(PdfContentByte)
效果图:
核心代码:
1.封面背景:
此部分代码来源于网络:
@Override protected void paintComponent(Graphics g) { super.paintComponent(g); //如果设置了背景图片则显示 if(backgroundImage != null) { int width = this.getWidth(); int height = this.getHeight(); int imageWidth = backgroundImage.getWidth(this); int imageHeight = backgroundImage.getHeight(this); switch(modeIndex) { //居中 case 0: { int x = (width - imageWidth) / 2; int y = (height - imageHeight) / 2; g.drawImage(backgroundImage, x, y, this); break; } //平铺 case 1: { for(int ix = 0; ix < width; ix += imageWidth) { for(int iy = 0; iy < height; iy += imageHeight) { g.drawImage(backgroundImage, ix, iy, this); } } break; } //拉伸 case 2: { g.drawImage(backgroundImage, 0, 0, width, height, this); break; } } } }
配合:backgroundImage.getScaledInstance(width, height, hints);来控制图片显示大小
2.JLabel纵向文本,JLabel大小自动适应
//设置纵向JLabel文本 private String setHtmlLabel(String text) { if (text == null) { return ""; } String str="<html>"; char[] arr = text.toCharArray(); for (char c : arr) { str=str+c+"<br>"; } //System.out.println(str); return str; } //设置JLable大小写 private void setVerticalLabelSize(JLabel label, java.awt.Font font) { String text = label.getText(); if (text == null) { return; } text=text.replaceAll("<html>","").replaceAll("<br>",""); FontMetrics fm = this.getFontMetrics(font); int w = fm.stringWidth("位"); int y = text.toCharArray().length * (font.getSize()+font.getSize()/4); label.setSize(w, y); // System.out.println(text+"--"+y+"--"+font.getSize()); }
3.JLabel拖动功能,来源于网络
//拖动监听器 class DragListener extends MouseInputAdapter { private JLabel dragComponet; /** 坐标点 */ Point point = new Point(0, 0); public DragListener(JLabel dragComponet) { this.dragComponet = dragComponet; } /** * 当鼠标拖动时触发该事件。 记录下鼠标按下(开始拖动)的位置。 */ public void mouseDragged(MouseEvent e) { // 转换坐标系统 Point newPoint = SwingUtilities.convertPoint(dragComponet, e.getPoint(), dragComponet.getParent()); // System.out.println(newPoint.x + " : " + newPoint.y); // 设置标签的新位置 dragComponet.setLocation(dragComponet.getX() + (newPoint.x - point.x), dragComponet.getY() + (newPoint.y - point.y)); // 更改坐标点 point = newPoint; } /** * 当鼠标按下时触发该事件。 记录下鼠标按下(开始拖动)的位置。 */ public void mousePressed(MouseEvent e) { // 得到当前坐标点 point = SwingUtilities.convertPoint(dragComponet, e.getPoint(), dragComponet.getParent()); //System.out.println(e.getPoint().x + " : " + e.getPoint().y); //System.out.println(point.x + " : " + point.y); } } //添加监听 DragListener titleDragListener = new DragListener(titleLabel); titleLabel.addMouseListener(titleDragListener); titleLabel.addMouseMotionListener(titleDragListener);
5.获取swing字体对应的TrueType 字体文件 (.ttf)路径
/** * 获取系统字体对应全路径Map * @return */ public static Map<String, String> getFontPathMap() { if (fontPathMap == null) { fontPathMap = new HashMap<String, String>(); GraphicsEnvironment eq = GraphicsEnvironment.getLocalGraphicsEnvironment(); //设置字体路径 java.awt.Font[] fs = eq.getAllFonts(); if (fs != null) { for (java.awt.Font f : fs) { //获取TrueType 字体文件 (.ttf)路径 String fontFilePath = FontManager.getFontPath(true) + File.separator + FontManager.getFileNameForFontName(f.getFontName()); fontPathMap.put(f.getFontName(), fontFilePath); } } } return fontPathMap; } /* * 根据swing字体生成PDF字体 */ public static BaseFont getPdfBaseFont(java.awt.Font swingFont) { String fontPath = getFontPathMap().get(swingFont.getFontName()); String defaultFontName = "STSong-Light"; String defaultEcoding = "UniGB-UCS2-H"; if (StringUtil.isNotBlank(fontPath)) { if (fontPath.toLowerCase().endsWith(".ttf")) { defaultFontName = fontPath; defaultEcoding = BaseFont.IDENTITY_H; } //字体集 if (fontPath.toLowerCase().endsWith(".ttc")) { defaultFontName = fontPath + ",1";//指定字体集中的第一个字体 defaultEcoding = BaseFont.IDENTITY_H; } } BaseFont bBaseFont = null; try { bBaseFont = BaseFont.createFont(defaultFontName, defaultEcoding, false); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bBaseFont; }
6.完成后封装成对象,使用itext生成PDF封面
import java.awt.Font; import java.awt.Point; /** *封面显示文本类 * @author changxian */ public class CoverShowTextBean { private String text;//文本内容 private Font font;//文本字体 private Point point;//文本位置(暂无用) private double x_percent;//文本位置X相对图片宽度百分比 private double y_percent;//文本位置Y相对图片高度百分比 public static int MODEL_HORIZONTAL=0; public static int MODEL_VERTICAL=1; private int model=MODEL_HORIZONTAL; public CoverShowTextBean(String text, Font font, Point point,int model) { this.text = text; this.font = font; this.point = point; this.model=model; } public CoverShowTextBean(String text, Font font, Point point) { this(text,font,point,MODEL_HORIZONTAL); } public CoverShowTextBean() { } public Font getFont() { return font; } public void setFont(Font font) { this.font = font; } public Point getPoint() { return point; } public void setPoint(Point point) { this.point = point; } public String getText() { return text; } public void setText(String text) { this.text = text; } public double getX(){ if(point!=null){ return point.getX(); } return -1d; } public double getY(){ if(point!=null){ return point.getY(); } return -1d; } /** * 获取横坐标占页面宽度的百分比<=1,point.x/wallpaper_width * @return double */ public double getX_percent() { return x_percent; } public void setX_percent(double x_percent) { this.x_percent = x_percent; } /** * 获取纵坐标占页面高度的百分比<=1,point.y/wallpaper_height * @return double */ public double getY_percent() { return y_percent; } public void setY_percent(double y_percent) { this.y_percent = y_percent; } public void setXPercent(double wallpaper_width){ this.setX_percent(getX()/wallpaper_width); } public void setYPercent(double wallpaper_height){ this.setY_percent(getY()/wallpaper_height); } public void setPositionPercent(double wallpaper_width,double wallpaper_height){ setXPercent(wallpaper_width); setYPercent(wallpaper_height); } public int getModel() { return model; } public void setModel(int model) { this.model = model; } }
import java.util.ArrayList; import java.util.List; /** *封面类 * @author changxian */ public class Cover { private String imgPath; private List<CoverShowTextBean> showTextList=new ArrayList<CoverShowTextBean>(); private boolean show; public boolean isShow() { return show; } public void setShow(boolean show) { this.show = show; } public String getImgPath() { return imgPath; } public void setImgPath(String imgPath) { this.imgPath = imgPath; } public List<CoverShowTextBean> getShowTextList() { return showTextList; } public void setShowTextList(List<CoverShowTextBean> showTextList) { this.showTextList = showTextList; } }
生成PDF封面:
/** * 生成封面 * @param writer * @param doc * @param cover * @throws IOException * @throws DocumentException */ public void setCover(PdfWriter writer, Document doc, Cover cover) throws IOException, DocumentException { float doc_height = doc.getPageSize().getHeight(); float doc_width = doc.getPageSize().getWidth(); //封面 Image tImgCover = Image.getInstance(cover.getImgPath()); /* 设置图片的位置 */ tImgCover.setAbsolutePosition(0, 0); /* 设置图片的大小 */ tImgCover.scaleAbsolute(doc_width, doc_height); doc.add(tImgCover);//加载图片 PdfContentByte cb = writer.getDirectContent(); List<CoverShowTextBean> showTextList = cover.getShowTextList(); if (showTextList != null && !showTextList.isEmpty()) { for (CoverShowTextBean show : showTextList) { Double t_x = doc_width * show.getX_percent(); Double t_y = doc_height * show.getY_percent(); BaseFont bf = CommonUtil.getPdfBaseFont(show.getFont()); if (show.getModel() == CoverShowTextBean.MODEL_HORIZONTAL) {//横向文本 cb.beginText(); cb.setFontAndSize(bf, show.getFont().getSize()); //cb.showTextAligned(PdfContentByte.ALIGN_LEFT,cover.getTitle(), t_x.intValue(),doc_height-t_y.intValue(), 0); //cb.setTextMatrix(doc_width, doc_width, doc_width, doc_width, doc_width, doc_width); //System.err.println("X=" + t_x.intValue() + "--Y=" + (doc_height - t_y.intValue())); cb.setTextMatrix(t_x.intValue(), doc_height - t_y.intValue() - show.getFont().getSize()); cb.showText(show.getText()); cb.endText(); } else {//纵向 String text = CommonUtil.removeHtmlSymbol(show.getText()); char[] textArr = text.toCharArray(); int j=show.getFont().getSize(); for (char c : textArr) { cb.beginText(); cb.setFontAndSize(bf, show.getFont().getSize()); cb.setTextMatrix(t_x.intValue(),doc_height - t_y.intValue() - j); cb.showText(c+""); j = j + show.getFont().getSize(); cb.endText(); } } } } doc.add(new Paragraph(" ")); doc.newPage(); }