3

i'm using a JTextPane as a cell renderer in my table (so i can control color, font, size and links easily). the problem is that lines get wrapped when the cell's get too small to contain the full text.

i know the number of expected text lines in advance (or i can just count), so i set the row's height accordingly.

how do i get the lines to crop (visually! i.e. in the middle of a letter) at the cell end?

thanks, asaf :-)

more info: i've tried two solutions i found on the net. one that involves setting my own EditroKit . the other is listed below, and involves overriding of setSize().
alas, none worked...

here is my renderer (apologies for messed up indentation...):

package textTable;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Insets;

import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.table.TableCellRenderer;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class LogRenderer extends JPanel implements TableCellRenderer {
    static class NoWrapTextPane extends JTextPane {
        public NoWrapTextPane () {
            super();
        }
        @Override
        public boolean getScrollableTracksViewportWidth() {
            return false;
        }
        @Override
        public void setSize(Dimension d) {
            if(d.width < getParent().getSize().width) {
                d.width = getParent().getSize().width;
            }
            super.setSize(d);
        }
    }

    private JTextPane textPane = new NoWrapTextPane();//JTextPane();
    private StyledDocument doc = textPane.getStyledDocument();
    private SimpleAttributeSet attr = new SimpleAttributeSet();
    private FontMetrics fontMetrics;

    public LogRenderer() {
    textPane.setMargin(new Insets(0,0,0,0));

        fontMetrics = textPane.getFontMetrics(getFont());

        StyleConstants.setFontFamily(attr, "monospaced");//"Courier"

    setLayout(new BorderLayout());
    add(textPane,BorderLayout.CENTER);
}

public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column) {
        String[] text;
        if (value != null && value instanceof String[]) {
            text = (String[]) value;
        } else {
            text = null;
        }
        try {
            doc.remove(0, doc.getLength());
            if (text != null) {
                int offset = 0;
                for (String line : text) {
                    doc.insertString(offset, line+"\n", attr);
                    offset += (line == null ? 0 : line.length()) +1;
                }
                int preferredHeight = fontMetrics.getHeight() *     text.length;
                if (preferredHeight != table.getRowHeight(row)) {
                    System.out.println("preferredHeight     "+preferredHeight+" = fontMetrics.getHeight() "+fontMetrics.getHeight()+" + text.length     "+text.length);
                    table.setRowHeight(row, preferredHeight);
                } 
            }
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
//      textPane.setToolTipText("hi");
        return this;
    }   
}
Asaf
  • 2,480
  • 4
  • 25
  • 33

1 Answers1

3

Use a custom renderer. Extending JLabel should give you ellipsis symbols to indicate truncation, but you can use JPanel and this approach to let clipping chop the result.

Addendum: The WrapEditorKit that you cited works well and seems to do what you want. In your LogRenderer, I think you can extend JEditorPane and set the editor in the constructor. For example:

private static class LogRenderer
    extends JEditorPane implements TableCellRenderer {

    public LogRenderer() {
        this.setEditorKit(new WrapEditorKit());
    }

    public Component getListCellRendererComponent(
        JList list, Object value, int index,
        boolean isSelected, boolean cellHasFocus) {
        this.setText((String) value);
        return this;
    }

    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
        this.setText((String) value);
        return this;
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • thanks for replying! i won't use JLabel because (a) i render multiple lines, and (b) i paint differently parts the text (color, size, links). in the second link (JPanel solution) you call drawString() yourself, which is the thing i'm trying to avoid... what i'm looking for is to use all the power of JTextPane but _turn off_ text wrapping. – Asaf Jan 27 '10 at 08:29
  • I added an example renderer using the kit you mentioned. – trashgod Jan 28 '10 at 04:17
  • 1
    It seems the Website java-sl.com is offline (anyone knows what happened to that site?) I found a archived version at archive.org - web.archive.org/web/20220203131713/http://java-sl.com/wrap.html – MadMike Nov 08 '22 at 08:04
  • 1
    @MadMike: I've added your [archive link](http://web.archive.org/web/20220203131713/java-sl.com/wrap.html) above. – trashgod Nov 08 '22 at 16:52