所以,我有这个JTexrtArea几乎完全满足我的需求。唯一不对的是线间距。我无法设置它。 (为什么不使用JTextPane?因为在JTextArea中可以更改间距,而JTextArea比JTextPane更轻,我的程序中有很多这样的内容。)
之前我问过这个question,这是我从用户StanislavL得到的答案:
要覆盖JTextArea的行间距,请查看PlainView(用于渲染PLainDocument)。
public void paint(Graphics g,Shape a)方法中有以下几行
drawLine(line, g, x, y);
y += fontHeight;
因此,您可以调整渲染固定y偏移。
在BasicTextAreaUI方法中创建视图。将其替换为您自己的PlainView实现
public View create(Element elem) {
Document doc = elem.getDocument();
Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
// build a view that support bidi
return createI18N(elem);
} else {
JTextComponent c = getComponent();
if (c instanceof JTextArea) {
JTextArea area = (JTextArea) c;
View v;
if (area.getLineWrap()) {
v = new WrappedPlainView(elem, area.getWrapStyleWord());
} else {
v = new PlainView(elem);
}
return v;
}
}
return null;
}
我掌握了他告诉我要做的一般想法,但我不知道该怎么做。 此外,我不想覆盖默认的JTextArea“属性”,我想有一个选择 - 使用默认的或使用自定义的。
只有JTextArea代码的更改才能来自
y += fontHeight
,
到
y+= (fontHeight +(or -) additionalSpacing)
。
我如何实现这一目标? 我使用/复制哪些课程? 我把它放在哪里? 我如何使它们可用? 如何让整个工作正常进行?
如果您认为这太具体而无法使用,也许有人可以编写一个关于如何在现有基础上100%创建自定义swing组件的一般教程。然后有人可以轻松地更改某些值,以便根据需要更好地调整它。
答案 0 :(得分:10)
我只想复制粘贴my answer from your other question。
我想改变JTextArea
行的间距
我的第一个想法是,压倒javax.swing.JTextArea#getRowHeight
就足够了。 javadoc清楚地说明了
定义行高的含义。这默认为字体的高度。
所以我希望通过覆盖这个方法,你可以调整定义,你会在行之间获得更多的间距。糟糕,没有工作。在JDK中快速搜索该方法的用法显示了相同的内容。它主要用于计算某些大小,但在组件内部绘制文本时肯定不会使用。
通过查看javax.swing.text.PlainView#paint
方法的源代码,我看到FontMetrics
已被使用,您可以轻松覆盖JTextArea
。所以第二种方法是扩展JTextArea
(bwah,扩展Swing组件,但它是用于概念验证)
private static class JTextAreaWithExtendedRowHeight extends JTextArea{
private JTextAreaWithExtendedRowHeight( int rows, int columns ) {
super( rows, columns );
}
@Override
public FontMetrics getFontMetrics( Font font ) {
FontMetrics fontMetrics = super.getFontMetrics( font );
return new FontMetricsWrapper( font, fontMetrics );
}
}
FontMetricsWrapper
类基本上委托除getHeight
方法之外的所有内容。在那个方法中,我在委托的结果中添加了10
@Override
public int getHeight() {
//use +10 to make the difference obvious
return delegate.getHeight() + 10;
}
这会导致更多行间距(并且插入符太长,但可能会调整)。
一个小截图来说明这一点(不如其他一些很好,但它表明这种方法可能有效):
小免责声明:这感觉就像一个丑陋的黑客,可能会导致意想不到的问题。我希望有人能找到更好的解决方案。
我个人更喜欢StanislavL提出的解决方案,但这为您提供了另一种选择
答案 1 :(得分:6)
这是一段代码。它没有完成。未实现包裹线之间的行间距。您可以获得WrappedPlainView
或PlainView
的完整来源,并在那里添加代码以获得所需的行间距
import javax.swing.*;
import javax.swing.plaf.basic.BasicTextAreaUI;
import javax.swing.text.*;
public class LineSpacingTextArea {
public static void main(String[] args) {
JTextArea ta=new JTextArea();
JFrame fr=new JFrame("Custom line spacing in JTextArea");
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ta.setText("Line 1\nLine 2\nLong text to show how line spacing works");
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setUI(new CustomTextAreaUI());
fr.add(new JScrollPane(ta));
fr.setSize(100,200);
fr.setLocationRelativeTo(null);
fr.setVisible(true);
}
static class CustomTextAreaUI extends BasicTextAreaUI {
public View create(Element elem) {
Document doc = elem.getDocument();
Object i18nFlag = doc.getProperty("i18n"/*AbstractDocument.I18NProperty*/);
if ((i18nFlag != null) && i18nFlag.equals(Boolean.TRUE)) {
// build a view that support bidi
return super.create(elem);
} else {
JTextComponent c = getComponent();
if (c instanceof JTextArea) {
JTextArea area = (JTextArea) c;
View v;
if (area.getLineWrap()) {
v = new CustomWrappedPlainView(elem, area.getWrapStyleWord());
} else {
v = new PlainView(elem);
}
return v;
}
}
return null;
}
}
static class CustomWrappedPlainView extends WrappedPlainView {
public CustomWrappedPlainView(Element elem, boolean wordWrap) {
super(elem, wordWrap);
}
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
super.layoutMajorAxis(targetSpan, axis, offsets, spans);
int ls=spans[0];
for (int i=0; i<offsets.length; i++) {
offsets[i]+=i*ls;
}
}
}
}