概述
可以说JTable是Swing组件中最重要的组件,只要程序和数据库打交道的程序必然有表格组件,而且多数情况下又不会很直白的把数据填到表格里,一般都会把各种组件放在表格里以便于对特定数据的呈现,也因此表格组件成了Swing里最让人头痛的组件。网上有很多如何把某个组件加载到表格的中的例子,但那些程序都只是用了极少的数据来演示,并不需要对表格进行刷新,因此那些例子里都没有关闭单元格编辑状态的代码,而当数据量大到需要多页显示时就出了问题,表格中的某列单元格使用了自定义的组件(诸如按钮之类的),当这些单元格被点击后再刷新表格的时会抛数组越界异常,像这样:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
at java.util.Vector.elementAt(Unknown Source)
at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
at javax.swing.JTable.setValueAt(Unknown Source)
at javax.swing.JTable.editingStopped(Unknown Source)
at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source)
at javax.swing.AbstractCellEditor.stopCellEditing(Unknown Source)
at javax.swing.JTable.columnMarginChanged(Unknown Source)
at javax.swing.table.DefaultTableColumnModel.fireColumnMarginChanged(Unknown Source)
at javax.swing.table.DefaultTableColumnModel.propertyChange(Unknown Source)
at java.beans.PropertyChangeSupport.fire(Unknown Source)
像这种问题很多人会以为问题是出在像表格里加载数据时出了错,又或者是某个单元格没有得到值等原因。
但真实的原因是没有关闭单元格的编辑状态,当点击某单元格后程序会使单元格状态变为编辑状态,如果此时不对表格内的数据重新加载的话是不会抛上述异常的,但只要一重新加载数据就立马抛异常,因此需要使用fireEditingStopped方法来关闭编辑状态。
我因为学习SQLite的需要而专门编写了一个带有JTable的程序,更详细的就不多说了,再此直接贴出代码以供参考
private JScrollPane createTable()
{
String[] columnHeaders = { "书名", "库存", "单价", "类型", "评分", "入库日期", "出版社", "联系电话" };
tableModel = new DefaultTableModel();
// 创建表格头部字段
tableModel.addColumn("");
for (String header : columnHeaders)
tableModel.addColumn(header);
tableModel.addColumn("操作");
JTable table = new JTable(tableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 表格选择为单选
table.setRowHeight(25); // 设置行高
table.setShowVerticalLines(false);// 使表格的列线条不显示
// 使第一列的大小固定不变
table.getColumn("").setPreferredWidth(25);
table.getColumn("").setMaxWidth(25);
table.getColumn("").setMinWidth(25);
// 设置表格排序,表格默认将所有值都作为字符串进行排序,
// 所以对于表格中已有字符型列可以不用自定义排序类
// 但需要对非字符串的列进行自定义排序
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel);
sorter.setComparator(2, new Comparator<Integer>()
{
public int compare(Integer o1, Integer o2)
{
return o1.compareTo(o2);
}
});
// 对单价列进行排序,由于单位已经被格式化了货币字符串
// 所以要对字符串进行转换后再比较
sorter.setComparator(3, new Comparator<String>()
{
public int compare(String o1, String o2)
{
BigDecimal b1 = new BigDecimal(o1.substring(1));
BigDecimal b2 = new BigDecimal(o2.substring(1));
return b1.compareTo(b2);
}
});
sorter.setComparator(6, new Comparator<java.sql.Date>()
{
public int compare(Date o1, Date o2)
{
return o1.compareTo(o2);
}
});
table.setRowSorter(sorter);
// 设置各列的呈现方式
new CheckBoxColumn(table.getColumn(""));
new LabelColumn(table.getColumn("书名"));
new LabelColumn(table.getColumn("单价"), null, Color.BLUE, SwingConstants.RIGHT);
new ProgressColumn(table.getColumn("库存"), Book.STORAGE_MAXIMUM);
new LabelColumn(table.getColumn("评分"), SwingConstants.CENTER);
new LabelColumn(table.getColumn("类型"));
new LabelColumn(table.getColumn("入库日期"), SwingConstants.LEFT);
new LabelColumn(table.getColumn("出版社"), SwingConstants.CENTER);
new ComboBoxColumn(table.getColumn("联系电话"));
new ButtonColumn(table.getColumn("操作"), "编辑", center);
return new JScrollPane(table);
}
public void updateTable()
{
// 清空表格模型内的数据
tableModel.getDataVector().clear();
tableModel.fireTableDataChanged();
new SwingWorker<List<BookView>, Vector>()
{
protected List<BookView> doInBackground() throws Exception
{
// 得到书籍的总数
bookTotal = center.getDataManager().getBookTotal();
// 根据当前的页数的返回一个结果集
List<BookView> books = center.getDataManager().getBookViewByPage(pageSize, pageNo);
for (BookView book : books)
{
Vector rowData = new Vector();
rowData.add(new Boolean(false));
rowData.add(book.getBookName());
rowData.add(book.getStorage());
rowData.add(NumberFormat.getCurrencyInstance().format(book.getPrice().doubleValue()));
rowData.add(book.getTypeName());
rowData.add(book.getGrade());
rowData.add(book.getStorageDate());
rowData.add(book.getPublishName());
rowData.add(book.getPublishPhone());
rowData.add(book.getId());
this.publish(rowData);
}
return books;
}
protected void process(List<Vector> chunks)
{
lblStatueBar.setText(StringHelper.LOADING);
for (Vector rowData : chunks)
{
tableModel.addRow(rowData);
}
}
protected void done()
{
lblStatueBar.setText("共有" + bookTotal + "条书籍记录!");
pageTotal = bookTotal / pageSize;
pageTotal += bookTotal / pageSize > 0 ? 1 : 0;
cboPage.removeAllItems();
for (int p = 1; p <= pageTotal; p++)
cboPage.addItem(p);
cboPage.setSelectedItem(pageNo);
chkDeleteAll.setSelected(false);
};
}.execute();
}
package gui.tableColumn;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class CheckBoxColumn extends AbstractCellEditor implements TableCellEditor, TableCellRenderer
{
private JCheckBox chkRender;
private JCheckBox chkEditor;
private Object value;
public CheckBoxColumn(TableColumn tc)
{
chkRender = new JCheckBox();
chkEditor = new JCheckBox();
chkEditor.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
fireEditingStopped();
}
});
tc.setCellEditor(this);
tc.setCellRenderer(this);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
chkRender.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
chkRender.setSelected((Boolean) value);
return chkRender;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
chkEditor.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
if(value!=null)
{
Boolean res = (Boolean)value;
res = !res;
this.value = res;
chkEditor.setSelected(res);
}
return chkEditor;
}
@Override
public Object getCellEditorValue()
{
return this.value;
}
}
package gui.tableColumn;
import gui.BookDialog;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import manager.ManagerCenter;
public class ButtonColumn extends AbstractCellEditor implements TableCellEditor, TableCellRenderer, ActionListener
{
private JButton btnRender;
private JButton btnEditor;
private Object value;
private ManagerCenter center;
public ButtonColumn(TableColumn tc, String name, ManagerCenter center)
{
this.center = center;
btnRender = new JButton(name);
btnEditor = new JButton(name);
btnEditor.addActionListener(this);
tc.setCellEditor(this);
tc.setCellRenderer(this);
}
@Override
public Object getCellEditorValue()
{
// TODO Auto-generated method stub
return this.value;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (hasFocus)
{
btnRender.setForeground(table.getForeground());
btnRender.setBackground(UIManager.getColor("Button.background "));
} else
if (isSelected)
{
btnRender.setForeground(table.getSelectionForeground());
btnRender.setBackground(table.getSelectionBackground());
} else
{
btnRender.setForeground(table.getForeground());
btnRender.setBackground(UIManager.getColor("Button.background "));
}
return btnRender;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
// TODO Auto-generated method stub
this.value = value;
if (isSelected)
{
btnEditor.setForeground(table.getSelectionForeground());
btnEditor.setBackground(table.getSelectionBackground());
} else
{
btnEditor.setForeground(table.getForeground());
btnEditor.setBackground(UIManager.getColor("Button.background "));
}
return btnEditor;
}
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
// System.out.println(value);
fireEditingStopped();
new BookDialog(center, Integer.parseInt(value.toString()));
}
}
package gui.tableColumn;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class ComboBoxColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor
{
private JComboBox cboRender;
private JComboBox cboEditor;
private Object value;
private JTable table;
public ComboBoxColumn(TableColumn tc)
{
tc.setCellEditor(this);
tc.setCellRenderer(this);
}
public Object getCellEditorValue()
{
return value;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (value != null)
{
String[] phones = value.toString().split("\|");
cboRender = new JComboBox(phones);
}
return cboRender;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
this.value = value;
this.table = table;
if (value != null)
{
String[] phones = value.toString().split("\|");
cboEditor = new JComboBox(phones);
cboEditor.addFocusListener(new FocusListener()
{
public void focusGained(FocusEvent e)
{
}
public void focusLost(FocusEvent e)
{
fireEditingStopped();
}
});
}
return cboEditor;
}
}
package gui.tableColumn;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import javax.swing.AbstractCellEditor;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class LabelColumn extends AbstractCellEditor implements TableCellEditor, TableCellRenderer
{
private Font font;
private Color fontColor;
private JLabel lblRender;
public LabelColumn(TableColumn tc, Font font, Color fontColor, int alignment)
{
lblRender = new JLabel();
lblRender.setOpaque(true);
tc.setCellEditor(this);
tc.setCellRenderer(this);
if (font != null)
this.font = font;
if (fontColor != null)
this.fontColor = fontColor;
if (alignment != -1)
lblRender.setHorizontalAlignment(alignment);
}
public LabelColumn(TableColumn tc, Font font)
{
this(tc, font, null, SwingConstants.LEFT);
}
public LabelColumn(TableColumn tc, Color fontColor)
{
this(tc, null, fontColor, SwingConstants.LEFT);
}
public LabelColumn(TableColumn tc, int alignment)
{
this(tc, null, null, alignment);
}
public LabelColumn(TableColumn tc)
{
this(tc, null, null, SwingConstants.LEFT);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
lblRender.setText(value != null ? value.toString() : "");
lblRender.setFont(this.font == null ? table.getFont() : this.font);
lblRender.setForeground(this.fontColor == null ? table.getForeground() : this.fontColor);
lblRender.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return lblRender;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
return null;
}
@Override
public Object getCellEditorValue()
{
// TODO Auto-generated method stub
return null;
}
}
package gui.tableColumn;
import java.awt.Component;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.AbstractCellEditor;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class ProgressColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor
{
private JProgressBar pbRender;
public ProgressColumn(TableColumn tc, int maximum)
{
pbRender = new JProgressBar();
pbRender.setMaximum(maximum);
pbRender.setBorder(null);
tc.setCellEditor(this);
tc.setCellRenderer(this);
}
public Object getCellEditorValue()
{
return null;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
pbRender.setString(value.toString());
pbRender.setStringPainted(true);
pbRender.setValue(Integer.parseInt(value.toString()));
return pbRender;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
return null;
}
}
最后
以上就是糟糕枫叶为你收集整理的再议将Swing组件与JTable的单元格组件的全部内容,希望文章能够帮你解决再议将Swing组件与JTable的单元格组件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复