在 JavaFX 中,如何计算文本所占像素的宽度
在 JavaFX 中,如何計算文本所占像素的寬度
- 注意事項
- 算法
- 代碼
- 計算單行文本的像素寬度
- 計算文本框尺寸
??JavaFX 的惱人之處在于很多基本的操作都要自己親力親為。有些時候,我們希望 TextArea 能自動根據文本內容換行以及調整大小。換行是 TextArea 中已經有的功能,不過這也帶來了新的問題。在 JavaFX 中,可以使用 Text 對象的方法 .getBoundsInLocal().getWidth() 測得文本的基本尺寸。不過,依然有很多要注意的問題。
【注意】
??不同的符號的尺寸是不同的,不僅是中文漢字與英文字母,就連運算符、數字、英文字母之間的尺寸也不盡相同。不要自行編寫自適應各種 Unicode 符號的算法。應該使用 JavaFX 內置的 API,如 Text 類的方法 Text對象.getBoundsInLocal().getWidth()。
注意事項
??主要的注意事項如下:
-
計算后最終的行寬值不會大于 TextArea 的行寬值。另外,當文本內容超過 TextArea 的最大寬度時,會觸發換行。因此,還需要計算 TextArea 自動換行后的行數。
-
用戶輸入的原始內容中就有可能包含換行。對這種情況可以有不同的處理方案,但是需要考慮這個問題。如果不選擇直接去除換行符,則需要先將用戶輸入分割成各個不含換行符的文本,然后分別統計這些文本的行數與最大行寬,最后加行數相加,并來取這些最大行寬中的最大值。
-
Windows 會將回車解釋成 \n\r,但 TextArea 清除文本中所有的 \r。換句話說,當在 Windows 輸入回車時,實際上輸入的是 \n\r。但當向 TextArea 輸入 \n\r 時,TextArea 會移除所有的 \r。從 TextArea 得到的字符串中不會包含任何 \r,TextArea 的換行符為 \n。
-
行數只能是整數。另外,如果使用整數除法,需要將結果加 1。因為不滿 1 行也需要占用一行。
-
考慮用戶的特殊輸入:
-
輸入為空串
-
輸入的內容全是換行符
-
輸入的內容存在連續的換行符
-
輸入的開頭是換行符
-
算法
??實現的算法大致如下:
(假設:當用戶輸入內容包含換行符時,不管是否連續,也直接進行原始輸出而不刪除。當用戶輸入的內容為空時,不報錯,也直接視文本長度為 0 來計算)
判斷輸入是否為 null 或空串,如果是,視文本行寬為 0,行數為 1。如果不是,進行下一步。
判斷輸入是否只有換行符,如果是,視文本行寬為 0,行數為換行符的個數。如果不是,進行下一步。
將輸入按照換行符分割成各個不含換行符的文本,然后先計算單個文本尺寸,最后疊加。方法如下:
計算單個文本的尺寸。方法如下:
求文本的原始像素長度。
計算文本的行寬值:取像素長度與單行文本最大長度之間的最小值。
計算文本的行數:將像素長度除以單行文本最大長度,然后向上取整。
計算整個文本的行寬值:取各個文本行寬值的最大值。
計算整個文本的行數:將各個文本行數值累加。
計算文本框的寬度:將文本的行寬值與文本框左右內邊距相加。
計算文本框的長度:將文本的行數乘以單行文本行高,然后加上文本框上下內邊距。
代碼
??核心代碼如下。
計算單行文本的像素寬度
public static double calculateTextPixelWidth(String text, Font font) {Text theText = new Text(text);theText.setFont(font);return theText.getBoundsInLocal().getWidth(); }計算文本框尺寸
/*** @param originText 內文本的內容* @param font 內文本的字體* @param lineSeparator 換行符的定義* @param originMaxWidth 內文本最大的行寬* @param rowExtension 對話框橫向兩端與內文本的邊距* @param originSingleHeight 內文本一行的高度* @param columnExtension 對話框縱向向兩端與內文本的邊距* @return 計算出的對話框的寬度。其中,[0] 代表寬度,[1] 代表高度*/public static double[] calculateTextBoxSize(String originText, Font font, String lineSeparator,double originMaxWidth, double rowExtension,double originSingleHeight, double columnExtension) {double maxRowLength = 0;int formattedColumnNum = 0;if (originText != null && !"".equals(originText)) {var texts = originText.split(lineSeparator);if (texts.length == 0) { // 如果文本中只有換行符maxRowLength = 0;formattedColumnNum = originText.length() + 1; // 注意要加 1} else {double singleRowLength = 0;for (var text : texts) {var singleOriginWidth = calculateTextPixelWidth(text, font);singleRowLength = Math.min(singleOriginWidth, originMaxWidth); // 注意:這是求最小值maxRowLength = Math.max(maxRowLength, singleRowLength); // 注意:這里求最大值formattedColumnNum += (int) (singleOriginWidth / originMaxWidth) + 1; // 注意要加 1}}}double[] result = new double[2];result[0] = maxRowLength + rowExtension * 2;result[1] = formattedColumnNum * originSingleHeight + columnExtension * 2;return result;}??對于 TextArea,其換行符為 \n,因此可以使用如下代碼:
/*** @param originText 內文本的內容* @param font 內文本的字體* @param originMaxWidth 內文本最大的行寬* @param rowExtension 對話框橫向兩端與內文本的邊距* @param originSingleHeight 內文本一行的高度* @param columnExtension 對話框縱向向兩端與內文本的邊距* @return 計算出的對話框的寬度。其中,[0] 代表寬度,[1] 代表高度*/ public static double[] calculateTextBoxSize(String originText, Font font,double originMaxWidth, double rowExtension,double originSingleHeight, double columnExtension) {String lineSeparator = "\n"; // TextArea 中的換行符為 '\n'return calculateTextBoxSize(originText, font, lineSeparator,originMaxWidth, rowExtension, originSingleHeight, columnExtension); } 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的在 JavaFX 中,如何计算文本所占像素的宽度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在 JavaFX 的 TextAre
- 下一篇: MySQL 免安装版的下载与配置教程