问题
I need to syncronise line spacing of my PDF ListItem and JTextArea in my GUI. I can do it by adjusting one or another.
And it all works great unil a ListItem (or JTextArea) is more than one line long (line wrap is set to true in JTextArea).
I can adjust the height between the two ListItems. That distance will also be applied to the height between two rows of a single multiline ListItem.
However, in my GUI, due to compononet boreders and default line spacing in JTextArea, those two are not the same. Difference is about one pixel, but on large scale that can accumulate and cause some issues.
So, is there any way I can set linespacing in JTextArea, or any way I can differentiate between spaceing between two list items and two rows of the same list item?
I'm all up for using external libraries of any kind and any kind of tricks it may take...
回答1:
To override JTextArea's line spacing take a look at the PlainView (used to render PLainDocument).
There are following lines in the public void paint(Graphics g, Shape a)
method
drawLine(line, g, x, y);
y += fontHeight;
So you can adapt the rendering fixing y offset.
In the BasicTextAreaUI
method to create view. Replace it with your own implementation of the 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;
}
回答2:
Control the space between your rows using the ParagraphAttribute SpaceBelow
. You can do this with 4 lines of code or less (see example below). You will need to use a JTextPane
to use these ParagraphAttributes (but JTextPane
and JTextArea` are so similar, you shouldn't notice a difference).
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class LineSpacingExample extends Box{
JTextPane modifiedTA;
//Modify this to whatever spacing you want between the rows.
static final float spaceBelow = 5.0f;
//Font height - automatically calculated by code below
int fontHeight = 0;
public LineSpacingExample(){
super(BoxLayout.X_AXIS);
//Demonstrating that the spacing is predictable
final JPanel leftBox = new CustomBox();
add(leftBox);
//Sets the amount of space below a row (only code you need to add)
DefaultStyledDocument pd = new DefaultStyledDocument();
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setSpaceBelow(sas, spaceBelow);
pd.setParagraphAttributes(0, pd.getLength(), sas, false);
modifiedTA= new JTextPane(pd);
add(modifiedTA);
//Calculates the font height in pixels
fontHeight = modifiedTA.getFontMetrics(modifiedTA.getFont()).getHeight();
}
/**
* @param args
*/
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new LineSpacingExample());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
//EXTRA! Paints the left hand side box - to show that the spacing is predictable in pixels
public class CustomBox extends JPanel{
public CustomBox() {
super();
setOpaque(true);
setBackground(Color.orange);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
int height = getSize().height;
int drawLocation = 2; //To account for padding on the TextPane
int row = 1;
while(drawLocation < height){
//Drawing the text row background
g.setColor(Color.blue);
g.fillRect(0, drawLocation, 50, fontHeight);
//Drawing the text row number
g.setColor(Color.white);
g.drawString(Integer.toString(row++), 0, drawLocation+14);
drawLocation += fontHeight;
//Drawing the space row
g.setColor(Color.green);
g.fillRect(0, drawLocation, 50, (int)spaceBelow);
drawLocation += spaceBelow;
}
}
};
}
回答3:
You can try to use a JTextPane
instead of a JTextArea
and set the line spacing accordingly to look like your ListItems.
SimpleAttributeSet set = new SimpleAttributeSet();
StyleConstants.setLineSpacing(set, 0.5f); // <--- your value here
textPane.setParagraphAttributes(set, true);
This will not affect the line spacing of existing text, so you should set the text afterwards.
来源:https://stackoverflow.com/questions/12725647/line-spacing-in-itext-list-item-or-jtextarea