2013-05-18 35 views
2

编辑:我添加了一个SSCCE代码如何删除/套的JTextArea边境JTable中单元格中的Nimbus外观

我在的TableCellRenderer扩展的JTextArea,因为我想实现多行文字环绕Mentioned in this SO question和工作精细。现在我遇到了Nimbus外观和感觉的奇怪问题。如下图所示,Nimbus正在为每个单元添加边框。 enter image description here

我的班级:

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JTextArea; 
import javax.swing.UIManager; 
import javax.swing.UIManager.LookAndFeelInfo; 
import javax.swing.border.EmptyBorder; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableModel; 
import javax.swing.table.TableRowSorter; 

public class TestJTableMultiline extends JFrame { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

public TestJTableMultiline() { 
    super("Multi-Line Cell Example"); 
    setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    DefaultTableModel dm = new DefaultTableModel() { 
     /** 
     * 
     */ 
     private static final long serialVersionUID = 1L; 
    public Class<String> getColumnClass(int columnIndex) { 
     return String.class; 
     } 
     public boolean isCellEditable(int row, int column) { 
     return false; 
     } 
    }; 
    dm.setDataVector(
     new Object[][]{ 
      {"A0, Line1\nA0, Line2\nA0, Line3", 
      "B0, Line1\nB0, Line2", 
      "C0, Line1"}, 
      {"A1, Line1", 
      "B1, Line1\nB1, Line2", 
      "C1, Line1"}, 
      {"A2, Line1", 
      "B2, Line1", 
      "C2, Line1"} 
      }, 
      new Object[] {"A", "B", "C"}); 

    JTable table = new JTable(dm); 
    table.setDefaultRenderer(String.class, new MultiLineTableCellRenderer()); 
    TableRowSorter<? extends TableModel> sort = new TableRowSorter<DefaultTableModel>(dm); 
    table.setRowSorter(sort); 
    JScrollPane scroll = new JScrollPane(table); 
    getContentPane().add(scroll); 
    setLocationByPlatform(true); 
    setSize(400, 430); 
    setVisible(true); 
    } 

    public static void main(String[] args) { 
     try{ 
      for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        UIManager.setLookAndFeel(info.getClassName()); 
        System.out.println("choosed nimbus"); 
        break; 
       } 
      } 
      }catch(Exception e){ 
       e.printStackTrace(); 
      } 
    TestJTableMultiline frame = new TestJTableMultiline(); 
    frame.addWindowListener(new WindowAdapter() { 
     public void windowClosing(WindowEvent e) { 
     System.exit(0); 
     } 
    }); 
    } 
} 

class MultiLineTableCellRenderer extends JTextArea 
implements TableCellRenderer { 
/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
private List<List<Integer>> rowColHeight = new ArrayList<List<Integer>>(); 

public MultiLineTableCellRenderer() { 
    setLineWrap(true); 
    setWrapStyleWord(true); 
    setOpaque(true); 
} 

@Override 
public Component getTableCellRendererComponent(
    JTable table, Object value, boolean isSelected, boolean hasFocus, 
    int row, int column) { 
    if (isSelected) { 
    setForeground(table.getSelectionForeground()); 
    setBackground(table.getSelectionBackground()); 
    } else { 
    setForeground(table.getForeground()); 
    setBackground(table.getBackground()); 
    } 
    setFont(table.getFont()); 
    if (hasFocus) { 
    setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); 
    if (table.isCellEditable(row, column)) { 
     setForeground(UIManager.getColor("Table.focusCellForeground")); 
     setBackground(UIManager.getColor("Table.focusCellBackground")); 
    } 
    } else { 
    setBorder(new EmptyBorder(1, 2, 1, 2)); 
    } 
    if (value != null) { 
    setText(value.toString()); 
    } else { 
    setText(""); 
    } 
    adjustRowHeight(table, row, column); 
    return this; 
} 

/** 
* Calculate the new preferred height for a given row, and sets the height on the table. 
*/ 
private void adjustRowHeight(JTable table, int row, int column) { 
    //The trick to get this to work properly is to set the width of the column to the 
    //textarea. The reason for this is that getPreferredSize(), without a width tries 
    //to place all the text in one line. By setting the size with the with of the column, 
    //getPreferredSize() returnes the proper height which the row should have in 
    //order to make room for the text. 
    int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth(); 
    setSize(new Dimension(cWidth, 1000)); 
    int prefH = getPreferredSize().height; 
    while (rowColHeight.size() <= row) { 
    rowColHeight.add(new ArrayList<Integer>(column)); 
    } 
    List<Integer> colHeights = rowColHeight.get(row); 
    while (colHeights.size() <= column) { 
    colHeights.add(0); 
    } 
    colHeights.set(column, prefH); 
    int maxH = prefH; 
    for (Integer colHeight : colHeights) { 
    if (colHeight > maxH) { 
     maxH = colHeight; 
    } 
    } 
    if (table.getRowHeight(row) != maxH) { 
    table.setRowHeight(row, maxH); 
    } 
} 

} 

What has been tried:

  1. 我试图setBorder(null)setBorder(BorderFactory.createLineBorder(Color.black))和其他各种颜色,如表forground和背景颜色。

  2. 然后,我看着this SO问题,并尝试了解决方案,但我无法解决边界问题。我也尝试完全删除setBorder调用,但结果是一样的。

  3. 我也试图消除这一SO问题

提到如何解决与灵气看看这个边界问题,并感到JTable中单元格边框。

注:我得到了与其他外观和感觉良好的看法。

+0

为了更好地帮助越早,张贴[SSCCE] (http://sscce.org/)。 –

+0

@AndrewThompson它在这里http://stackoverflow.com/questions/16597431/how-to-implement-multiple-line-text-renderer-in-jtable – Ashish

+2

不存在JScrollPane,如果是的话删除/或JTextArea在JScrollPane和JScrollPane中的边界太 – mKorbel

回答

3
  • 这可能在JDK 1.7.0或更高版本的工作:

    MultiLineTableCellRenderer r = new MultiLineTableCellRenderer(); 
    UIDefaults d = new UIDefaults(); 
    d.put("TextArea.borderPainter", new Painter() { 
        @Override public void paint(Graphics2D g, Object o, int w, int h) {} 
    }); 
    r.putClientProperty("Nimbus.Overrides", d); 
    r.putClientProperty("Nimbus.Overrides.InheritDefaults", false); 
    
    table.setDefaultRenderer(String.class, r); 
    

enter image description here

SSCCE

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.*; 
import javax.swing.border.*; 
import javax.swing.plaf.*; 
import javax.swing.table.*; 
import javax.swing.UIManager.LookAndFeelInfo; 

public class TestJTableMultiline2 { 
    public JComponent makeUI() { 
    String[] columnNames = {"A", "B", "C"}; 
    Object[][] data = { 
     {"A0, Line1\nA0, Line2\nA0, Line3", "B0, Line1\nB0, Line2", "C0, Line1"}, 
     {"A1, Line1", "B1, Line1\nB1, Line2", "C1, Line1"}, 
     {"A2, Line1", "B2, Line1", "C2, Line1"} 
    }; 
    DefaultTableModel model = new DefaultTableModel(data, columnNames) { 
     @Override public Class<?> getColumnClass(int column) { 
     return String.class; 
     } 
     @Override public boolean isCellEditable(int row, int column) { 
     return false; 
     } 
    }; 
    JTable table = new JTable(model); 
    table.setAutoCreateRowSorter(true); 

    MultiLineTableCellRenderer r = new MultiLineTableCellRenderer(); 
    UIDefaults d = new UIDefaults(); 
    d.put("TextArea.borderPainter", new Painter() { 
     @Override public void paint(Graphics2D g, Object o, int w, int h) {} 
    }); 
    r.putClientProperty("Nimbus.Overrides", d); 
    r.putClientProperty("Nimbus.Overrides.InheritDefaults", false); 

    table.setDefaultRenderer(String.class, r); 
    return new JScrollPane(table); 
    } 
    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     @Override public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 
    public static void createAndShowGUI() { 
    try { 
     for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 
     if ("Nimbus".equals(info.getName())) { 
      UIManager.setLookAndFeel(info.getClassName()); 
      break; 
     } 
     } 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
    JFrame f = new JFrame("Multi-Line Cell Example 2"); 
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    f.getContentPane().add(new TestJTableMultiline2().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 

class MultiLineTableCellRenderer extends JTextArea implements TableCellRenderer { 
    private List<List<Integer>> rowColHeight = new ArrayList<List<Integer>>(); 
    //private Border fhb = UIManager.getBorder("Table.focusCellHighlightBorder"); 
    //private Border epb = BorderFactory.createEmptyBorder(2,5,2,5); 
    public MultiLineTableCellRenderer() { 
    super(); 
    setLineWrap(true); 
    setWrapStyleWord(true); 
    setOpaque(true); 
    //System.out.println(fhb.getBorderInsets(this)); 
    //setBorder(epb); 
    } 
    @Override 
    public Component getTableCellRendererComponent(
    JTable table, Object value, boolean isSelected, 
    boolean hasFocus, int row, int column) { 
    setFont(table.getFont()); 
    setText(value != null ? value.toString() : ""); 
    setMargin(new Insets(2,5,2,5)); 
    //setBorder(hasFocus ? fhb : epb); 
    if (isSelected) { 
     setForeground(table.getSelectionForeground()); 
     setBackground(table.getSelectionBackground()); 
    } else { 
     setForeground(table.getForeground()); 
     setBackground(table.getBackground()); 
    } 
    adjustRowHeight(table, row, column); 
    return this; 
    } 

    /** 
    * Calculate the new preferred height for a given row, and sets the height on the table. 
    * http://blog.botunge.dk/post/2009/10/09/JTable-multiline-cell-renderer.aspx 
    */ 
    private void adjustRowHeight(JTable table, int row, int column) { 
    //The trick to get this to work properly is to set the width of the column to the 
    //textarea. The reason for this is that getPreferredSize(), without a width tries 
    //to place all the text in one line. By setting the size with the with of the column, 
    //getPreferredSize() returnes the proper height which the row should have in 
    //order to make room for the text. 
    //int cWidth = table.getTableHeader().getColumnModel().getColumn(column).getWidth(); 
    int cWidth = table.getCellRect(row, column, false).width; //Ignore IntercellSpacing 
    setSize(new Dimension(cWidth, 1000)); 
    int prefH = getPreferredSize().height; 
    while (rowColHeight.size() <= row) { 
     rowColHeight.add(new ArrayList<Integer>(column)); 
    } 
    List<Integer> colHeights = rowColHeight.get(row); 
    while (colHeights.size() <= column) { 
     colHeights.add(0); 
    } 
    colHeights.set(column, prefH); 
    int maxH = prefH; 
    for (Integer colHeight : colHeights) { 
     if (colHeight > maxH) { 
     maxH = colHeight; 
     } 
    } 
    if (table.getRowHeight(row) != maxH) { 
     table.setRowHeight(row, maxH); 
    } 
    } 
} 
+0

像魅力 – Ashish

+0

一样工作+1但为什么要为计算PreferredSize ,我认为doLayout()可以做到这一点(或许我的懒惰) – mKorbel

+0

@mKorbel谢谢。 ''doLayout()''可能比上面的方式更容易。你会告诉我一个链接到你的文章? (不知道我看到你的帖子使用''doLayout()'',但我失去了一个链接) – aterai