当前位置: 首页 > 知识库问答 >
问题:

如何使用Java获得定义了宽度的多行富文本字段(任意字体、任意字体大小)所需的高度?

卞经业
2023-03-14

我有一个X字体字符串(如Arial字体)在定义宽度值时具有Y高度,这样字符串就可以进入多行。我需要计算所需的高度,以便所需的字符串可以适合它。Apache POI中的行自动大小是不可能的,因为我需要行合并单元格中存在的富文本字符串(任何字体和高度)的高度,在这种情况下自动大小不起作用。

共有1个答案

宇文德明
2023-03-14

找到了使用JTextPane渲染文本的解决方案

示例代码最初是一种字体和fontsize的整个文本。但由于JTextPane提供了StyledDocument,因此也应该可以处理富文本内容。(待办事项)。

代码注释了为什么需要代码部分。

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

public class CreateExcelCellWrapTextRenderedHeight {

 public static void main(String[] args) throws Exception {
  XSSFWorkbook workbook = new XSSFWorkbook();

  Font font = workbook.createFont();
  font.setFontName("Arial");
  font.setFontHeightInPoints((short)19);

  CellStyle cellstyle = workbook.createCellStyle();
  cellstyle.setWrapText(true);
  cellstyle.setFont(font);

  Sheet sheet = workbook.createSheet();

  sheet.setColumnWidth(3, 25*256);

  Row row = sheet.createRow(0);

  String text = "String cell content\nhaving line wrap.\nIt has new line marks and then a long text without new line marks.\nFollowed by short text part.\n\nGreetings from Axel so long";

  Cell cell = row.createCell(2);
  cell.setCellValue(text);
  cell.setCellStyle(cellstyle);

  CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 2, 4);
  sheet.addMergedRegion(cellRangeAddress);

//__________________________calculate text height by rendering the text

  //get the used font 
  Font usedfont = workbook.getFontAt(cell.getCellStyle().getFontIndex());

  //get the used font name
  String fontname = usedfont.getFontName();
System.out.println(fontname);
 
 //get the used font size
  short fontheight = usedfont.getFontHeightInPoints();
System.out.println(fontheight);

  //get the width of the colunms in pixels
  float colwidth = 0;
  for (int c = cellRangeAddress.getFirstColumn(); c <= cellRangeAddress.getLastColumn(); c++) {
   colwidth += sheet.getColumnWidthInPixels(c);
  }
System.out.println(colwidth);

  //get screen resolution
  int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
System.out.println(ppi);

  //create a font - correct the size to be appropriate to the screen resolution
  java.awt.Font awtFont = new java.awt.Font(fontname, java.awt.Font.PLAIN, Math.round(fontheight/(72f/ppi)));

  //create a JTextPane to render the text
  javax.swing.JTextPane textpane = new javax.swing.JTextPane();
 
  //set the font
  textpane.setFont(awtFont);

  //set dimension of the JTextPane to colwidth and maximum height
  java.awt.Dimension dimension = new java.awt.Dimension(Math.round(colwidth), Integer.MAX_VALUE);
  textpane.setSize(dimension);

  //Excels cells have different line spacing than default JTextPane
  javax.swing.text.MutableAttributeSet attributeset = new javax.swing.text.SimpleAttributeSet(textpane.getParagraphAttributes());
  javax.swing.text.StyleConstants.setLineSpacing(attributeset, 0.1f);

  javax.swing.text.StyledDocument document = textpane.getStyledDocument();
  document.setParagraphAttributes(0, document.getLength(), attributeset, true);

  //insert the text - TODO: handle rich text
  document.insertString(0, text, null);

  //resize dimension to preferred height
  dimension.setSize(Math.round(colwidth), textpane.getPreferredSize().getHeight());
  textpane.setPreferredSize(dimension);
 
  double textwidthpx = dimension.getWidth();
System.out.println(textwidthpx);
  double textheightpx = dimension.getHeight();
System.out.println(textheightpx);

  //textheightpx is in pixel, but we need points
  float textheight = (float)textheightpx * (72f/ppi);
System.out.println(textheight);

//__________________________
 
  row.setHeightInPoints(textheight);

  workbook.write(new FileOutputStream("CreateExcelCellWrapTextRenderedHeight.xlsx"));
  workbook.close();

  javax.swing.SwingUtilities.invokeLater(new Runnable() {
   public void run() {
    new TextPaneDemo(textpane).setVisible(true);
   }
  });

 }

 static class TextPaneDemo extends javax.swing.JFrame {

  TextPaneDemo(javax.swing.JTextPane textpane) {
   super("TextPaneDemo");
   this.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE);
   this.getContentPane().add(textpane, java.awt.BorderLayout.CENTER);
   this.pack();
  }
          
 }

}

JTextPane的内容与Excel单元格中的内容几乎完全相同。所以高度基本上是准确的。

使用多种字体和字体大小的测试结果也不差。

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;

public class CreateExcelCellWrapTextRenderedHeightTest {

 static float getPreferredHeight(Cell cell, String text, CellRangeAddress cellrangeaddress) throws Exception {
  //get the used font 
  Font usedfont = cell.getSheet().getWorkbook().getFontAt(cell.getCellStyle().getFontIndex());

  //get the used font name
  String fontname = usedfont.getFontName();

  //get the used font size
  short fontheight = usedfont.getFontHeightInPoints();

  //get the width of the colunms in pixels
  float colwidth = 0;
  for (int c = cellrangeaddress.getFirstColumn(); c <= cellrangeaddress.getLastColumn(); c++) {
   colwidth += cell.getSheet().getColumnWidthInPixels(c);
  }

  //get screen resolution
  int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();

  //create a font - correct the size to be appropriate to the screen resolution
  java.awt.Font awtFont = new java.awt.Font(fontname, java.awt.Font.PLAIN, Math.round(fontheight/(72f/ppi)));

  //create a JTextPane to render the text
  javax.swing.JTextPane textpane = new javax.swing.JTextPane();

  //set the font
  textpane.setFont(awtFont);

  //set dimension of the JTextPane to colwidth and maximum height
  java.awt.Dimension dimension = new java.awt.Dimension(Math.round(colwidth), Integer.MAX_VALUE);
  textpane.setSize(dimension);

  //Excels cells have different line spacing than default JTextPane
  javax.swing.text.MutableAttributeSet attributeset = new javax.swing.text.SimpleAttributeSet(textpane.getParagraphAttributes());
  javax.swing.text.StyleConstants.setLineSpacing(attributeset, 0.1f);

  javax.swing.text.StyledDocument document = textpane.getStyledDocument();
  document.setParagraphAttributes(0, document.getLength(), attributeset, true);

  //insert the text
  document.insertString(0, text, null);

  //resize dimension to preferred height
  dimension.setSize(Math.round(colwidth), textpane.getPreferredSize().getHeight());
  textpane.setPreferredSize(dimension);

  double textheightpx = dimension.getHeight();

  //textheightpx is in pixel, but we need points
  float textheight = (float)textheightpx * (72f/ppi);

  return textheight;
 }

 public static void main(String[] args) throws Exception {
  Workbook workbook = new XSSFWorkbook();

  Sheet sheet = workbook.createSheet();
  sheet.setColumnWidth(3, 30*256);

  String text = "String cell content\nhaving line wrap.\nIt has new line marks and then a long text without new line marks.\nFollowed by short text part.\n\nGreetings from Axel so long";

  String[] fontnames = new String[]{"Arial", "Times New Roman", "Courier New", "Arial Black"};

  for (int r = 0; r < 16; r++) {

   Font font = workbook.createFont();
   font.setFontName(fontnames[(r % 4)]);

   font.setFontHeightInPoints((short)(r+6));

   CellStyle cellstyle = workbook.createCellStyle();
   cellstyle.setWrapText(true);
   cellstyle.setFont(font);

   Row row = sheet.createRow(r);

   Cell cell = row.createCell(2);
   cell.setCellValue(text);
   cell.setCellStyle(cellstyle);

   CellRangeAddress cellrangeaddress = new CellRangeAddress(r, r, 2, 4);
   sheet.addMergedRegion(cellrangeaddress);

   float textheight = getPreferredHeight(cell, text, cellrangeaddress);
   row.setHeightInPoints(textheight);

  }
  
  FileOutputStream out = new FileOutputStream("CreateExcelCellWrapTextRenderedHeightTest.xlsx");
  workbook.write(out);
  out.close();
  workbook.close();

 }

}
 类似资料:
  • 问题内容: 我正在使用一个第三方库,该库通过GraphicsEnvironment:getAllFonts()调用来访问字体。这包括属于JRE和操作系统的字体注册表中的字体。 但是在连接到我们服务器的客户端计算机上,我很可能无法在这些位置中的任何一个中安装字体。那么,如何使JRE可以使用其他字体,以便此调用将它们选中呢?有没有办法扩大其搜索路径? 我可以使用Font.createFont()调用从

  • 我会保持简短直截了当,这样我就明白了: > vw根据视区宽度更改字体大小。 VH根据视区高度更改字体大小。 我的问题是; 有没有一种方法可以根据视区的宽度和高度来缩放我的字体大小?因此,改变浏览器的高度和宽度将适当地缩放我的字体大小。 我这样问是因为我想根据它们所在的容器适当地缩放我的文本大小,我的问题是容器缩放到100%的宽度和100%的高度。因此,根据高度和宽度来缩放文本大小似乎是合乎逻辑的,

  • 我有一个字体对象,我需要字体的宽度和高度。我知道getSize()返回字体的高度,因为字体的点号通常是高度,但在确定字体的宽度时,我不知所措。 或者,能够确定字体支持的每个特定字符的宽度也是一个可接受的解决方案。 我的最佳猜测是,宽度是在使用loadFont方法时指定的,但文档没有指定size参数是表示字体的宽度还是高度。 使用的所有字体都是单空格字体,如DejaVu Sans mono、GNU

  • 我需要得到pdf中给定单词的x,y,宽度和高度。因此,在以后解析同一类型的文件时,我可以从坐标本身获取值。如何使用java从PDF中获取单词的位置。

  • 我正在尝试在itext 5中使用TextField。我的字体名是“微軟正黑體英文是“Microsoft JhengHei”。我想用粗体和黑色的字体。 初始化字体(3是字体。BOLD|字体。ITALIC和BC是我的基本颜色) 我有一个文本字段变量,并将fontZh设置为setFont。 pdf结果只有字体样式、大小和颜色是正确的。但这种大胆和不自然是行不通的。

  • 问题内容: 我正在使用Java绘制一些文本,但是对我来说很难计算字符串的宽度。例如:zheng中国…这个字符串要占用多长时间? 问题答案: 对于单个字符串,您可以获取给定图形字体的度量,然后使用该度量来计算字符串大小。例如: 如果您有更复杂的文本布局要求,例如在给定宽度内流动一段文本,则可以创建一个对象,例如此示例(来自docs):