2009-06-08 39 views
31

Tôi đang cố triển khai Trình chỉnh sửa bảng tùy chỉnh như được mô tả trong this tutorial. Tôi muốn có dòng kết xuất của mỗi văn bản dài cho ô đã cho. Ý tưởng là sử dụng TextArea làm trình kết xuất đồ họa, vì nó hỗ trợ gói dòng. Tuy nhiên, đoạn mã sau không cư xử như mong đợi:Làm thế nào để bọc đường trong một tế bào jtable?

public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer { 

    @Override 
    public Component getTableCellRendererComponent(
      JTable table, 
      Object value, 
      boolean isSelected, 
      boolean hasFocus, 
      int row, 
      int column) { 
     this.setText((String)value); 
     this.setWrapStyleWord(true);    
     this.setLineWrap(true);   
     return this; 
    } 

} 

tôi đặt renderer này với

table.setDefaultRenderer(String.class, new LineWrapCellRenderer()); 

Nhưng các mục tế bào ở lại nào. Nếu tôi thêm this.setBackground(Color.YELLOW) vào phương pháp getTableCellRendererComponent(), tất cả các ô có màu vàng như mong đợi, nhưng không được bao bọc.

Bất kỳ ý tưởng nào?

CẬP NHẬT: Như Michael Borgwardt đã nêu trong phần nhận xét, vấn đề không phải là dòng bọc, nhưng chiều cao hàng: Hàng JTables có kích thước cố định, vì vậy nếu ô đang tăng (lót), chúng ta phải tăng chiều cao hàng. Nhưng bao nhiêu? Tôi sẽ kiểm tra xem điều này có đáng giá SO-câu hỏi khác không. Nếu không, tôi sẽ thêm giải pháp này vào đây.

Update2: Các mã sau đây sẽ quyết định chiều cao hàng (nếu đặt trong getTableCellRendererComponent()):

int fontHeight = this.getFontMetrics(this.getFont()).getHeight(); 
int textLength = this.getText().length(); 
int lines = textLength/this.getColumns() +1;//+1, cause we need at least 1 row.   
int height = fontHeight * lines;    
table.setRowHeight(row, height); 
+3

không thay đổi trạng thái bảng trong trình kết xuất đồ họa - như trong ** không bao giờ ** – kleopatra

+15

Kính thưa Cleopatra !!! Vui lòng cho chúng tôi giải pháp làm việc thay vì chỉ nói rằng bạn có thể làm điều này tốt hơn. –

+0

Vui lòng kiểm tra http://stackoverflow.com/questions/33937074/jtable-cell-wrapping/38932843#38932843 – Yougesh

Trả lời

11

vấn đề là rằng chiều cao của hàng trong JTable là cố định, vì vậy nó không chỉ là vấn đề của việc có một renderer bọc S; Tôi không chắc tại sao nó lại không, nhưng nếu nó đã làm, văn bản được gói sẽ bị cắt xén - hoặc có thể đó chính xác là những gì bạn đang thấy. Để điều chỉnh chiều cao của hàng, bạn cần đặt riêng từng hàng.

+0

Điều đó có vẻ là vấn đề. Sau khi thiết lập chiều cao hàng thành một giá trị lớn hơn, dòng bọc sẽ xuất hiện. Vấn đề bây giờ: Làm thế nào để có được chiều cao hoàn hảo mới cho. – Arvodan

+0

Nhìn vào bài viết tôi đã liên kết đến, nó có mã ví dụ mà tôi có thể dễ dàng thích nghi với một giải pháp làm việc hoàn hảo. –

+9

Liên kết bạn đề nghị không làm việc nữa ... có lẽ một cuộc tranh luận ủng hộ thực sự hiển thị mã ở đây? –

6

Xin chào Tôi đã gặp vấn đề tương tự nhưng giải pháp mà tôi đã triển khai được lấy cảm hứng từ mẫu có sẵn từ Hướng dẫn Java để vẽ văn bản nhiều dòng và vẽ văn bản trên ô bằng API văn bản.

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; 
    } 
} 

Nó thay đổi kích thước heigth hàng quá nhưng nó cũng nó chỉ khi kết xuất đồ họa này được sử dụng cho một cột duy nhất.

Và đây là cách tôi đã sử dụng để gọi nó để hiển thị bảng của tôi.

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

Tôi muốn sử dụng mã này trong chương trình của mình. Nếu tôi có thể, theo giấy phép nào tôi nên bao gồm mã này? –

+0

Phần lớn mã này xuất phát từ một hướng dẫn về miền công cộng không nên ngăn chặn bất kỳ chính sách cấp phép nào, tôi giả sử. –

+0

-1 để thay đổi trạng thái bảng trong ... phương pháp vẽ ?? Thậm chí còn tồi tệ hơn so với việc thực hiện nó trong getXXRendererComp vốn không phải là tuyệt đối ... và không có gì khác: tạo thành phần mới trên mỗi cuộc gọi, không triển khai các gợi ý định cỡ .. đôi khi nên có nhiều hơn một phiếu bầu;) – kleopatra

0

Viết tiêu đề trong HTML. Đây là một ví dụ về cái mà tôi có. Vấn đề duy nhất mà tôi đang gặp phải là tôi gặp khó khăn khi họ di chuyển trong JPanel nếu tôi điều chỉnh chiều cao của tiêu đề.

myTable.getColumnModel().getColumn(1).setPreferredWidth(75); 
    myTable.getColumnModel().getColumn(1).setHeaderValue("<html><b>Day Of<br>Week</b></html>"); 
+3

câu hỏi không phải là về tiêu đề ... – kleopatra

0

setBounds sử dụng trên phần renderer (xem dưới đây)

import java.awt.*; 
import java.io.*; 
import java.util.*; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.table.*; 

public class MultiWrapColDemo { 
    public static void main(String[] args) throws FileNotFoundException { 
    EventQueue.invokeLater(new ShowIt()); 
    } 
} 

class ShowIt implements Runnable { 
    @Override 
    public void run() { 
    JTable table = new JTable(); 
    table.getColumnModel().addColumnModelListener(new WrapColListener(table)); 
    table.setDefaultRenderer(Object.class, new JTPRenderer()); 

    // examples: 
// table.setIntercellSpacing(new Dimension(40, 20)); 
// table.setIntercellSpacing(new Dimension(4, 2)); 

    Vector<Vector<String>> dataVector = new Vector<Vector<String>>(); 
    String lorem1 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore"; 
    String lorem2 = "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"; 

    for (int i = 0; i < 12; i++) { 
     Vector<String> row = null; 
     if (i % 4 == 0) { 
     row = new Vector<String>(Arrays.asList(new String[] { "iggle", lorem1, "poggle", "poke" })); 
     } else if (i % 4 == 1) { 
     row = new Vector<String>(Arrays.asList(new String[] { lorem2, "piggle", "poggle", lorem1 })); 
     } else if (i % 4 == 2) { 
     row = new Vector<String>(Arrays.asList(new String[] { lorem1, "piggle", lorem2, "poke" })); 
     } else 
     row = new Vector<String>(Arrays.asList(new String[] { "iggle", lorem2, "poggle", lorem2 })); 
     dataVector.add(row); 
    } 
    Vector<String> columnIdentifiers = new Vector<String>(Arrays.asList(new String[] { "iggle", "piggle", "poggle", 
     "poke" })); 
    table.getTableHeader().setFont(table.getTableHeader().getFont().deriveFont(20f).deriveFont(Font.BOLD)); 
    ((DefaultTableModel) table.getModel()).setDataVector(dataVector, columnIdentifiers); 
    JFrame frame = new JFrame("MultiWrapColTable"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    JScrollPane jsp = new JScrollPane(table); 
    frame.getContentPane().add(jsp); 
    frame.pack(); 
    frame.setBounds(50, 50, 800, 500); 
    frame.setVisible(true); 
    } 
} 


// if the renderer on a column (or the whole table) is not a JTextComponent calculating its preferredSize will not do 
// any wrapping ... but it won't do any harm.... 
class JTPRenderer extends JTextPane implements TableCellRenderer { 
    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, 
     int row, int column) { 
    setText(value.toString()); 
    return this; 
    } 
} 

class WrapColListener implements TableColumnModelListener { 

    JTable m_table; 

    WrapColListener(JTable table){ 
    m_table = table; 
    } 

    void refresh_row_heights() { 
    int n_rows = m_table.getRowCount(); 
    int n_cols = m_table.getColumnCount(); 
    int intercell_width = m_table.getIntercellSpacing().width; 
    int intercell_height = m_table.getIntercellSpacing().height; 
    TableColumnModel col_model = m_table.getColumnModel(); 
    // these null checks are due to concurrency considerations... much can change between the col margin change 
    // event and the call to refresh_row_heights (although not in this SSCCE...) 
    if(col_model == null) return; 
    // go through ALL rows, calculating row heights 
    for (int row = 0; row < n_rows; row++) { 
     int pref_row_height = 1; 
     // calculate row heights from cell, setting width constraint by means of setBounds... 
     for (int col = 0; col < n_cols; col++) { 
     Object value = m_table.getValueAt(row, col); 
     TableCellRenderer renderer = m_table.getCellRenderer(row, col); 
     if(renderer == null) return; 
     Component comp = renderer.getTableCellRendererComponent(m_table, value, false, false, 
      row, col); 
     if(comp == null) return; 
     int col_width = col_model.getColumn(col).getWidth(); 
     // constrain width of component 
     comp.setBounds(new Rectangle(0, 0, col_width - intercell_width, Integer.MAX_VALUE)); 
     // getPreferredSize then returns "true" height as a function of attributes (e.g. font) and word-wrapping 
     int pref_cell_height = comp.getPreferredSize().height + intercell_height; 
     if (pref_cell_height > pref_row_height) { 
      pref_row_height = pref_cell_height; 
     } 
     } 
     if (pref_row_height != m_table.getRowHeight(row)) { 
     m_table.setRowHeight(row, pref_row_height); 
     } 
    } 
    } 

    @Override 
    public void columnAdded(TableColumnModelEvent e) { 
    refresh_row_heights(); 

    } 

    @Override 
    public void columnRemoved(TableColumnModelEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

    @Override 
    public void columnMoved(TableColumnModelEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

    @Override 
    public void columnMarginChanged(ChangeEvent e) { 
    refresh_row_heights(); 
    } 

    @Override 
    public void columnSelectionChanged(ListSelectionEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

} 

Trên đây hoạt động tốt trong SSCCE này ...nhưng trong thế giới thực, với phông chữ phức tạp hơn, nhiều văn bản hơn và các bảng lớn hơn bạn bắt đầu gặp phải sự cố. Do đó, tôi đề xuất bên dưới một phiên bản mới của lớp Listener cùng với một phiên bản mới của trình kết xuất đồ họa (chỉ để giới thiệu việc sử dụng một phông chữ phức tạp ...). Thay thế những điều này vào SSCCE ở trên nếu quan tâm ...

/* 
* This class reflects the fact that 1) when you drag a column boundary using the mouse a very large number of 
* ChangeEvents are generated and 2) with more complex fonts, more text and larger tables ("real world") the amount 
* of computation in calculating the row heights becomes significant and leads to an unresponsive GUI, or worse. 
* This "first" strategy to address this involves setting a pause between the detection of a change event and the 
* refreshing of the rows. Naturally this involves a Timer, the run() method of which is not the EDT, so it 
* must then submit to EventQueue.invokeLater... 
* The larger the table, the more text involved, and the more complex the fonts... the more ingenuity will have to 
* be used in coping with the potentially vast amount of computation involved in getting the ideal row heights. This 
* is in the nature of the beast. Ideas might involve: 
* 1) adjusting the row heights immediately only for rows which are visible or likely to be visible (Viewport), and 
* then making successive calls to EventQueue.invokeLater to deal with all the other rows 
* 2) giving cells a "memory" of their heights as a function of the allowed width. Unfortunately it will not allow 
* the possibility of interpolating intermediate values because the question of whether a line wraps may hinge on a 
* single pixel difference, although an imperfect solution to this would be err on the side of caution, i.e. pretend 
* that a column is a little thinner than it is to cause wrapping before it is strictly necessary... particularly when 
* cells are out of view... 
* ... other ideas...(?) 
*/ 
class FirstRealWorldWrapColListener implements TableColumnModelListener { 

    JTable m_table; 
    final static long PAUSE_TIME = 50L; 
    java.util.Timer m_pause_timer = new java.util.Timer("pause timer", true); 
    TimerTask m_pause_task; 

    class PauseTask extends TimerTask{ 
    @Override 
    public void run() { 
     EventQueue.invokeLater(new Runnable(){ 
     @Override 
     public void run() { 
      refresh_row_heights(); 
      System.out.println("=== setting m_pause_task to null..."); 
      m_pause_task = null; 
     }}); 
    } 
    } 

    FirstRealWorldWrapColListener(JTable table){ 
    m_table = table; 
    } 


    void queue_refresh(){ 
    if(m_pause_task != null){ 
     return; 
    } 
    System.out.println("=== scheduling..."); 
    m_pause_task = new PauseTask(); 
    m_pause_timer.schedule(m_pause_task, PAUSE_TIME); 

    } 

    void refresh_row_heights() { 

    int n_rows = m_table.getRowCount(); 
    int n_cols = m_table.getColumnCount(); 
    int intercell_width = m_table.getIntercellSpacing().width; 
    int intercell_height = m_table.getIntercellSpacing().height; 
    TableColumnModel col_model = m_table.getColumnModel(); 
    // these null checks are due to concurrency considerations... much can change between the col margin change 
    // event and the call to refresh_row_heights (although not in this SSCCE...) 
    if(col_model == null) return; 
    // go through ALL rows, calculating row heights 
    for (int row = 0; row < n_rows; row++) { 
     int pref_row_height = 1; 
     // calculate row heights from cell, setting width constraint by means of setBounds... 
     for (int col = 0; col < n_cols; col++) { 
     Object value = m_table.getValueAt(row, col); 
     TableCellRenderer renderer = m_table.getCellRenderer(row, col); 
     if(renderer == null) return; 
     Component comp = renderer.getTableCellRendererComponent(m_table, value, false, false, 
      row, col); 
     if(comp == null) return; 
     int col_width = col_model.getColumn(col).getWidth(); 
     // constrain width of component 
     comp.setBounds(new Rectangle(0, 0, col_width - intercell_width, Integer.MAX_VALUE)); 
     // getPreferredSize then returns "true" height as a function of attributes (e.g. font) and word-wrapping 
     int pref_cell_height = comp.getPreferredSize().height + intercell_height; 
     if (pref_cell_height > pref_row_height) { 
      pref_row_height = pref_cell_height; 
     } 
     } 
     if (pref_row_height != m_table.getRowHeight(row)) { 
     m_table.setRowHeight(row, pref_row_height); 
     } 
    } 
    } 

    @Override 
    public void columnAdded(TableColumnModelEvent e) { 
// refresh_row_heights(); 
    queue_refresh(); 

    } 

    @Override 
    public void columnRemoved(TableColumnModelEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

    @Override 
    public void columnMoved(TableColumnModelEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

    @Override 
    public void columnMarginChanged(ChangeEvent e) { 
// refresh_row_heights(); 
    queue_refresh(); 
    } 

    @Override 
    public void columnSelectionChanged(ListSelectionEvent e) { 
    // probably no need to call refresh_row_heights 

    } 

} 

// if the renderer on a column (or the whole table) is not a JTextComponent calculating its preferredSize will not do 
// any wrapping ... but it won't do any harm.... 
class JTPRenderer extends JTextPane implements TableCellRenderer { 
    Font m_default_font, m_big_font, m_default_alternate_font, m_big_alternate_font; 
    HashMap<AttributedCharacterIterator.Attribute, Object> m_red_serif_attr_map; 
    // 
    JTPRenderer() { 
    m_default_font = getFont(); 
    m_big_font = m_default_font.deriveFont(m_default_font.getSize() * 1.5f); 
    m_red_serif_attr_map = new HashMap<AttributedCharacterIterator.Attribute, Object >(); 
    m_red_serif_attr_map.put(TextAttribute.FAMILY, Font.SERIF); 
    m_red_serif_attr_map.put(TextAttribute.FOREGROUND, Color.RED); 
    m_red_serif_attr_map.put(TextAttribute.WIDTH, TextAttribute.WIDTH_EXTENDED); 
    m_default_alternate_font = m_default_font.deriveFont(m_red_serif_attr_map); 
    m_big_alternate_font = m_big_font.deriveFont(m_red_serif_attr_map); 
    // simpler alternate font: 
// m_default_alternate_font = m_default_font.deriveFont(Font.BOLD | Font.ITALIC); 
// m_big_alternate_font = m_big_font.deriveFont(Font.BOLD | Font.ITALIC); 
    } 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, 
     int row, int column) { 
    int rc = row + column; 
    if(rc % 4 == 2) 
     setFont(rc % 5 == 1 ? m_big_alternate_font : m_default_alternate_font); 
    else 
     setFont(rc % 5 == 1 ? m_big_font : m_default_font); 
    setText(value.toString()); 
    return this; 
    } 

} 
0

Như đã lưu ý ở trên chiều cao hàng cần được tính toán nhưng giải pháp hiện tại có thể được cải thiện. Trong thực tế, nó không làm việc cho tôi. jtxt.getColumns() đã trở về 0 gây ra chia cho 0. Dưới đây là một số mã tôi nghĩ là sạch hơn:

// set the width on the jTextArea causing a calc of preferred height 
jtxt.setSize(table.getWidth(), Short.MAX_VALUE); 
int prefH = jtxt.getPreferredSize().height; 
table.setRowHeight(row, prefH); 
3

Ngoài câu hỏi này, tôi muốn chia sẻ với bạn giải pháp cho trình chỉnh sửa ô đa dòng. Đó là một chút hacky (cửa hàng tham chiếu đến hàng chỉnh sửa), nhưng thực hiện công việc.

import javax.swing.*; 
import javax.swing.table.TableCellEditor; 
import java.awt.*; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 

class MultilineTableCellEditor extends AbstractCellEditor implements TableCellEditor { 

    JComponent component = new JTextArea(); 
    JTable table; 
    int lastRowIndex; 

    public MultilineTableCellEditor() { 
     JTextArea textArea = ((JTextArea) component); 
     textArea.setLineWrap(true); 
     textArea.setWrapStyleWord(true); 
     textArea.addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentResized(ComponentEvent e) { 
       super.componentResized(e); 
       table.setRowHeight(lastRowIndex, (int) (textArea.getPreferredSize().getHeight())); 
      } 
     }); 
     textArea.addKeyListener(new KeyAdapter() { 
      @Override 
      public void keyTyped(KeyEvent e) { 
       super.keyTyped(e); 
       table.setRowHeight(lastRowIndex, (int) (textArea.getPreferredSize().getHeight())); 
      } 
     }); 
    } 

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, 
               int rowIndex, int vColIndex) { 
     this.table = table; 
     lastRowIndex = rowIndex; 

     ((JTextArea) component).setText((String) value); 
     component.setFont(table.getFont()); 

     return component; 
    } 

    public Object getCellEditorValue() { 
     return ((JTextArea) component).getText(); 
    } 
} 

Được sử dụng như vậy:

JTable table = new JTable(tableModel) { 
     // Cell renderer by Alessandro Rossi (posted as solution to this question) 
     MultilineTableCell renderer = new MultilineTableCell(); 
     MultilineTableCellEditor editor = new MultilineTableCellEditor(); 

     @Override 
     public TableCellRenderer getCellRenderer(int row, int column) { 
      if (column == multilineColumn) { 
       return renderer; 
      } 
      return super.getCellRenderer(row, column); 
     } 

     @Override 
     public TableCellEditor getCellEditor(int row, int column) { 
      if (column == multilineColumn) { 
       return editor; 
      } 
      return super.getCellEditor(row, column); 
     } 
    }; 
+0

+1 Tôi đã tìm kiếm dòng wrapper cho một biên tập viên trong nhiều tuần, cuối cùng đã tìm thấy điều này và nó làm việc hoàn hảo cho tôi. Cảm ơn bạn! – ppw

1

Tôi loạng choạng trong vấn đề này giống nhau, và tôi cần phải sửa đổi một chút mã mà nó được viết ở đây, vì vậy tôi đính kèm phiên bản của riêng tôi:

import java.awt.Component; 
import javax.swing.JTable; 
import javax.swing.JTextArea; 
import javax.swing.table.TableCellRenderer; 

public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer { 

    @Override 
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, 
     int row, int column) { 
    this.setText((String) value); 
    this.setWrapStyleWord(true); 
    this.setLineWrap(true); 

    int fontHeight = this.getFontMetrics(this.getFont()).getHeight(); 
    int textLength = this.getText().length(); 
    int lines = textLength/this.getColumnWidth(); 
    if (lines == 0) { 
     lines = 1; 
    } 

    int height = fontHeight * lines; 
    table.setRowHeight(row, height); 

    return this; 
} 

} 
Các vấn đề liên quan