JTable调用自定义单元格渲染器方法…持续

可以在http://www.splashcd.com/jtable.tarfind可以编译的源代码

我是新来的语言,所以我不确定这是否可以接受的行为。

我创build了一个JTable来显示接收到的每条消息的一行(每20秒收到一条消息)。 其中一个表列可以包含大量的文本,所以我创build了一个自定义的单元格渲染器,该单元渲染器相应地包装并设置行高。

除了一旦表格显示第一行,它就会按预期工作,每秒调用一次大约十次的单元格渲染器,直到用户closures表格为止。

一旦我在那里得到大约20行,表格变得非常迟缓,需要2-8秒来调整列的大小,爬升或下降,或者用选定的背景颜色渲染选定的行。

我在渲染器中插入了一个print语句,所以我可以看到getTableCellRendererComponent方法被调用的次数。

我禁用了工具提示,并禁用了所有单元格编辑。 当添加一个新行或调整表的大小时,我确实有一个侦听器将视图滚动到最后一行。

当我正在查看屏幕(不是触摸鼠标或键盘)时,是否应该每秒调用getTableCellRendererComponent方法?

TIA

  • aaaaach

  • 你需要doLayout()

  • 下一级:-),那么你可以设置JTextComponents Maximum visible row ,只需要很less的努力

在这里输入图像描述

的doLayout()

 import java.awt.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.text.*; //http://tips4java.wordpress.com/2008/10/26/text-utilities/ public class AutoWrapTest { public JComponent makeUI() { String[] columnNames = {" Text Area Cell Renderer "}; Object[][] data = { {"123456789012345678901234567890"}, {"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"}, {"----------------------------------------------0"}, {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd" + "dddddddxdddddddddddddddddddddddddddddddddddddddddddddd" + "dddddddddddx>>>>>>>>>>>>>>>>>>>>>>>>>|"}, {">>>>>>>>>>>>ddddddddddddddddddddddddddddddddddddddddddddddddddd" + "ddddddx>>>>>>>>>>>>>>>>>>>>>>>>>>|"}, {"a|"}, {">>>>>>>>bbbb>>>>>>>>>>>>>>>>>>>|"}, {">>>>>>>>>>>>>>>>>>|"}, {">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd" + "dddddddxdddddddddddddd123456789012345678901234567890dddddd" + "dddddddddddddddddddddddddddddddddddddx>>>>>>>>>>>>>>>>>>>>" + ">>>>>|"}, {">>>>>>>>>>>>>dddddddddddddd123456789012345678901234567890dddddd" + "dddddddddddddddddddddddddddddddddddddxdddddddddddddd123456" + "789012345678901234567890dddddddddddddddddddddddddddddddddd" + "ddddd123456789012345678901234567890ddddx>>>>>>>>>>>>>>>>>>" + ">>>>>>>|"},}; TableModel model = new DefaultTableModel(data, columnNames) { private static final long serialVersionUID = 1L; @Override public boolean isCellEditable(int row, int column) { return false; } }; JTable table = new JTable(model) { private static final long serialVersionUID = 1L; @Override public void doLayout() { TableColumn col = getColumnModel().getColumn(0); for (int row = 0; row < getRowCount(); row++) { Component c = prepareRenderer(col.getCellRenderer(), row, 0); if (c instanceof JTextArea) { JTextArea a = (JTextArea) c; int h = getPreferredHeight(a) + getIntercellSpacing().height; if (getRowHeight(row) != h) { setRowHeight(row, h); } } } super.doLayout(); } private int getPreferredHeight(JTextComponent c) { Insets insets = c.getInsets(); View view = c.getUI().getRootView(c).getView(0); int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS); return preferredHeight + insets.top + insets.bottom; } }; table.setEnabled(false); table.setShowGrid(false); table.setTableHeader(null); table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer()); //table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane sp = new JScrollPane(table); sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); sp.setPreferredSize(new Dimension(250, 533)); JPanel p = new JPanel(new BorderLayout()); p.add(sp); return p; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new AutoWrapTest().makeUI()); f.setLocation(100, 100); f.pack(); f.setVisible(true); } } class TextAreaCellRenderer extends JTextArea implements TableCellRenderer { private static final long serialVersionUID = 1L; private final Color evenColor = new Color(230, 240, 255); public TextAreaCellRenderer() { super(); setLineWrap(true); setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); } @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()); setBackground((row % 2 == 0) ? evenColor : getBackground()); } setFont(table.getFont()); setText((value == null) ? "" : value.toString()); return this; } } 

为了从TableCellRenderer获得最高性能,请确保每次调用getTableCellRenderer都不要创build组件的新实例。 组装一次,并将它们保存为类的字段。

另外,您还需要确保您使用的每个组件都有以下方法重写:

  • validation
  • 废止
  • 重新validation
  • 重绘
  • 中的firePropertyChange

(你可能想要硬编码isOpaque )。

有关更多信息,请参阅: http : //docs.oracle.com/javase/6/docs/api/javax/swing/tree/DefaultTreeCellRenderer.html

这个问题似乎源于在自定义单元格渲染器中有JTable的setRowHeight() ,因为它调用自定义单元格渲染器,将其投入无限循环。

我不得不添加一个检查,以查看当前行高是否与计算出的包装行高度匹配。 如果是这样,我没有尝试再次setRowHeight()。

更正后的代码:

 import java.awt.Component; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.UIManager; import javax.swing.table.TableCellRenderer; //custom cell renderer for word wrapping, but if you use, you have to //implement zebra striping functionality which the default renderer has public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer { private int numOfTimesCalled; @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { System.out.println("Line Wrap Cell Renderer Called: " + numOfTimesCalled++); System.out.println("row:"+ row + ", col:" + column); //set up the row size based on the number of newlines in the text in the cell int fontHeight = this.getFontMetrics(this.getFont()).getHeight(); int numWraps = value.toString().split("\r\n|\r|\n").length; int rowHeight = fontHeight * numWraps; //if the calculated rowHeight is the same as the row height of row, // then don't call setRowHeight again, as doing so will throw us into // an infinite loop if(rowHeight != table.getRowHeight(row)) { table.setRowHeight(row, rowHeight); //configure word wrapping setWrapStyleWord(true); setLineWrap(true); //use the table's font setFont(table.getFont()); } //zebra striping, because whatever cell uses this renderer loses the //default cell renderer zebra striping if(isSelected) { setBackground(table.getSelectionBackground()); } else { if(row%2 == 1) { setBackground(UIManager.getColor("Table.alternateRowColor")); } else { setBackground(table.getBackground()); } } this.setText(value.toString()); return this; } }