How to wrap lines in a jtable cell?

前端 未结 8 1043
面向向阳花
面向向阳花 2020-11-29 09:11

I\'m trying to implement a custom TableRenderer as described in this tutorial. I\'d like to have the renderer line-wrap each text that is to long for the given cell. The i

8条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-29 09:44

    Hi I had your same problem but the solution I implemented is inspired by the sample available from the Java Tutorial for drawing multiline text and draws the text on the cell using the text APIs.

    http://java.sun.com/docs/books/tutorial/2d/text/drawmulstring.html

    import java.awt.Component;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.font.FontRenderContext;
    import java.awt.font.LineBreakMeasurer;
    import java.awt.font.TextLayout;
    import java.text.AttributedCharacterIterator;
    import java.text.AttributedString;
    import java.text.BreakIterator;
    
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableCellRenderer;
    
    
    public class MultilineTableCell 
        implements TableCellRenderer {
        class CellArea extends DefaultTableCellRenderer {
            /**
             * 
             */
            private static final long serialVersionUID = 1L;
            private String text;
            protected int rowIndex;
            protected int columnIndex;
            protected JTable table;
            protected Font font;
            private int paragraphStart,paragraphEnd;
            private LineBreakMeasurer lineMeasurer;
    
            public CellArea(String s, JTable tab, int row, int column,boolean isSelected) {
                text = s;
                rowIndex = row;
                columnIndex = column;
                table = tab;
                font = table.getFont();
                if (isSelected) {
                    setForeground(table.getSelectionForeground());
                    setBackground(table.getSelectionBackground());
                }
            }
            public void paintComponent(Graphics gr) {
                super.paintComponent(gr);
                if ( text != null && !text.isEmpty() ) {
                    Graphics2D g = (Graphics2D) gr;
                    if (lineMeasurer == null) {
                        AttributedCharacterIterator paragraph = new AttributedString(text).getIterator();
                        paragraphStart = paragraph.getBeginIndex();
                        paragraphEnd = paragraph.getEndIndex();
                        FontRenderContext frc = g.getFontRenderContext();
                        lineMeasurer = new LineBreakMeasurer(paragraph,BreakIterator.getWordInstance(), frc);
                    }
                    float breakWidth = (float)table.getColumnModel().getColumn(columnIndex).getWidth();
                    float drawPosY = 0;
                    // Set position to the index of the first character in the paragraph.
                    lineMeasurer.setPosition(paragraphStart);
                    // Get lines until the entire paragraph has been displayed.
                    while (lineMeasurer.getPosition() < paragraphEnd) {
                        // Retrieve next layout. A cleverer program would also cache
                        // these layouts until the component is re-sized.
                        TextLayout layout = lineMeasurer.nextLayout(breakWidth);
                        // Compute pen x position. If the paragraph is right-to-left we
                        // will align the TextLayouts to the right edge of the panel.
                        // Note: this won't occur for the English text in this sample.
                        // Note: drawPosX is always where the LEFT of the text is placed.
                        float drawPosX = layout.isLeftToRight()
                            ? 0 : breakWidth - layout.getAdvance();
                        // Move y-coordinate by the ascent of the layout.
                        drawPosY += layout.getAscent();
                        // Draw the TextLayout at (drawPosX, drawPosY).
                        layout.draw(g, drawPosX, drawPosY);
                        // Move y-coordinate in preparation for next layout.
                        drawPosY += layout.getDescent() + layout.getLeading();
                    }
                    table.setRowHeight(rowIndex,(int) drawPosY);
                }
            }
        }
        public Component getTableCellRendererComponent(
                JTable table, Object value,boolean isSelected, boolean hasFocus, int row,int column
            )
        {
            CellArea area = new CellArea(value.toString(),table,row,column,isSelected);
            return area;
        }   
    }
    

    It resizes row heigth too but it does it well only when this renderer is used for a single column.

    And this is the way I used to invoke it for render my table.

    final int wordWrapColumnIndex = ...;
    myTable = new JTable() {    
        public TableCellRenderer getCellRenderer(int row, int column) {
            if (column == wordWrapColumnIndex ) {
                return wordWrapRenderer;
            }
            else {
                return super.getCellRenderer(row, column);
            }
        }
    };
    

提交回复
热议问题