Edit: I have added a SSCCE code
编辑:我添加了一个SSCCE代码
I have extended JTextArea in TableCellRenderer because I wanted to achieve the Multiline text wrapping Mentioned in this SO question and that is working fine. Now I have ran into weird problem with Nimbus look and feel. Nimbus is adding a border with every cell as shown in the below picture.
我在TableCellRenderer中扩展了JTextArea,因为我想实现在这个SO问题中提到的多行文本包装,它运行得很好。现在我遇到了光轮的外观和感觉的奇怪问题。Nimbus正在为每个单元添加边框,如下图所示。
My Class:
我的类:
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:
已经试过:
-
I have tried
setBorder(null)
andsetBorder(BorderFactory.createLineBorder(Color.black))
and various other color like forground and background color of the table.我尝试过setBorder(null)和setBorder(BorderFactory.createLineBorder(Color.black))以及表的forground和背景色等各种颜色。
-
Then I looked at this SO question and tried that solution as well but I am not able to resolve the border problem. I have also tried removing setBorder call altogether but the results are same.
然后我看了这个问题,也尝试了那个解决方案,但是我不能解决边界问题。我也尝试过完全删除setBorder调用,但是结果是一样的。
-
I have also tried removing the cell border in jtable mentioned in this SO question
我还尝试删除这个SO问题中提到的jtable中的单元格边界
How can I resolve this border problem with Nimbus look and feel.
如何用Nimbus look and feel解决这个边界问题?
Note: I am getting nice view with other look and feel.
注意:我得到了很好的视图与其他的外观和感觉。
1 个解决方案
#1
3
-
This might work in JDK 1.7.0 or later:
这可能在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);
SSCCE
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);
}
}
}
#1
3
-
This might work in JDK 1.7.0 or later:
这可能在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);
SSCCE
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);
}
}
}