SWT中带SWT.WRAP属性的StyledText如何根据内容计算适配高度
解决方案
方案一:直接调用系统自带计算逻辑(推荐)
SWT控件内置的computeSize方法已经自动处理了自动换行、字体DPI、控件边距等所有场景,不需要自己手动实现行数计算,代码最简且准确率最高:
// 控件完成首次布局后,先获取当前可用宽度 int availableWidth = styledText.getClientArea().width; // 未完成首次布局时可以用预设宽度或者父容器宽度兜底 if (availableWidth <= 0) { availableWidth = ((GridData) styledText.getLayoutData()).widthHint; } // 传入宽度约束,让系统自动计算适配的高度 Point requiredSize = styledText.computeSize(availableWidth, SWT.DEFAULT); // 直接设置高度提示 ((GridData) styledText.getLayoutData()).heightHint = requiredSize.y; // 触发父容器重排生效 styledText.getParent().layout();
你只需要在StyledText的ModifyListener(内容变化)和父容器的ControlListener(宽度变化)中触发上述逻辑即可实现自动适配效果。
方案二:手动修正行数计算逻辑
如果需要自定义行数计算规则,可以修正原代码的问题:原代码使用textExtent直接计算文本总宽度再除法得到的行数没有适配SWT的换行规则(比如单词换行、空白字符拆分),同时没有计入控件内边距、行间距、边框高度,修正后代码如下:
private int calculateRequiredHeight() { GC gc = new GC(styledText); try { gc.setFont(styledText.getFont()); int fontHeight = gc.getFontMetrics().getHeight(); int lineSpacing = styledText.getLineSpacing(); int singleLineHeight = fontHeight + lineSpacing; int clientWidth = styledText.getClientArea().width; int logicLineCount = styledText.getLineCount(); int realLineCount = 0; for (int i = 0; i < logicLineCount; i++) { int lineStart = styledText.getOffsetAtLine(i); int lineEnd = (i == logicLineCount - 1) ? styledText.getCharCount() : styledText.getOffsetAtLine(i + 1); String lineContent = styledText.getText(lineStart, lineEnd - 1); // 按照SWT的换行规则计算当前逻辑行拆分的实际行数 int offset = 0; int breakCount = 0; while (offset < lineContent.length()) { int step = gc.breakText(lineContent.substring(offset), clientWidth); if (step <= 0) break; offset += step; breakCount++; } realLineCount += Math.max(1, breakCount); } // 计入控件边框、内边距得到最终高度 Rectangle trim = styledText.computeTrim(0, 0, clientWidth, realLineCount * singleLineHeight); return trim.height; } finally { gc.dispose(); } }
使用时直接将返回值设置为heightHint即可:
((GridData) styledText.getLayoutData()).heightHint = calculateRequiredHeight(); styledText.getParent().layout();
内容的提问来源于stack exchange,提问作者LppEdd
相关产品推荐
相关产品推荐

