Line spacing in iText list item or JTextArea

风格不统一 提交于 2020-01-24 11:00:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!