上周继续用Swing做小项目,其中我在实现数据的查询过程中发现,以往的习惯是更新数据筛选条件都要去数据库中重新查询,但是我把数据库部署到云端发现这样查询数据压力较大,程序运行很慢,最好是少执行数据库的操作,多在本地实现数据的修改,于是我就仔细研究了研究JTable的一些功能,发现JTable的作为容器还是可以往里面添加一些控件来调用RowSorter对表中数据进行筛选和排序的。
一,通过点击列名实现数据排序
单击表头,可以针对这一列进行排序,代码很简单
final TableRowSorter ts;
ts = new TableRowSorter(jTable1.getModel()); //由于使用的NetBeans做的,Jtable已经new好了,故此省略
jTable1.setRowSorter(ts);
只需给要筛选的table设置一个RowSorter即可
二,实现Excel中每列筛选的功能
这里我采用的方式是在往表里添加数据的同时往Jcombobox中也添加item,当然还要考虑重复的问题,这样保证筛选选项都是已出现的数据,我的理想状态是能把Jcombobox放到table的表头TableHeader里面去,但是翻了不少代码发现自己弄不明白,只好暂时放弃,若有高人指点不胜感谢!
//接上面的代码,还是使用获取的TableRowSorter
ts.setRowFilter(RowFilter.regexFilter(jCB1.getSelectedItem().toString(), 0)); //(要匹配的值,列的下标)
只要设置一下tablemodel ,这样表中的boolean会被自动显示成一个checkbox,我把它放到第一列
table.setModel(new DefaultTableModel(){ //重写DefaultTableModel的getColumnClass方法,若是在NetBeans中的话需要定制代码
@Override
public Class getColumnClass(int columnIndex) {
Object value = getValueAt(0, columnIndex);
if(value!=null){
return value.getClass();
}
else{
return super.getClass();
}
}
});
接下来是给表头中画一个checkbox用以全选,注意是画出来的也就是说只具有显示效果,单击全选的效果还需要单击事件实现
class MyCheckBoxRenderer extends JCheckBox implements TableCellRenderer {
public MyCheckBoxRenderer() {
this.setBorderPainted(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
// TODO Auto-generated method stub
return this;
}
}
final MyCheckBoxRenderer check = new MyCheckBoxRenderer();
table.getColumnModel().getColumn(0).setHeaderRenderer(check);
table.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (table.getColumnModel().getColumnIndexAtX(e.getX()) == 0) {//如果点击的是第0列,即checkbox这一列
JCheckBox Checkbox = (JCheckBox) check;
boolean b = !check.isSelected();
check.setSelected(b);
table.getTableHeader().repaint();
for (int i = 0; i < table.getRowCount(); i++) {
table.getModel().setValueAt(b, i, 0);//把这一列都设成和表头一样
}
}
}
});
这样效果就达到了,我还给table内容加了一个MouseClicked,单击某一行就改变这一行的选中状态,也就是改变第一列的boolean值即可,就不贴代码了。
四,设置table背景透明
这种效果在web上是很容易的,我想在Swing上实现想来想去还是得用table,但是如果没有内容填充的话table的的背景太丑了,通过多方查找先总结如下:
首先JTable是存在于JScrollPane这个容器上的,也需要把这个容器设为透明
jScrollPane.getViewport().setOpaque(false);
jScrollPane.setOpaque(false);
这时候再把table设置成透明
jTable.setOpaque(false);
但是这个时候每一行的数据还不是透明的,没了边框后反而更丑了,需要设置透明的渲染器来渲染每一行
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(SwingConstants.CENTER); //这里是设置了字体居中
renderer.setOpaque(false);//渲染器设置为透明
jTable.getColumnModel().getColumn(0).setCellRenderer(renderer); //这里因为我只用了一列,所以只getColumn(0)来进行设置
接上面的图,我是想做成邮箱那个效果,未读消息加粗,点击查看后字体恢复原样,查找后明白,同样需要设置渲染器来达到这个效果。
重写DefaultTableCellRenderer的getTableCellRendererComponent方法
public class MessageFont extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (((Message)value).getMstate().equals("0")) { //这里我是判断的放入表中的数据对象中的某一个值,可根据具体情况修改
Font tempF = cell.getFont();
String NameF = tempF.getName();
//int StyleF = tempF.getStyle();
int SizeF = tempF.getSize();
cell.setFont(new Font(NameF, Font.BOLD, SizeF)); //重新设定Font,具体查看API
return cell;
} else {
return cell;
}
}
}
这样结合上面的同时设置为透明的需求的话代码应该是这样
MessageFont renderer = new MessageFont();
renderer.setHorizontalAlignment(SwingConstants.CENTER);
renderer.setOpaque(false);//渲染器设置为透明
jTable.setOpaque(false);//table设置透明 再此之前已将JScrollPane设置为透明
jTable.getColumnModel().getColumn(0).setCellRenderer(renderer);
http://blog.csdn.net/b_h_l/article/details/7771944
http://my.oschina.net/soitravel/blog/35425
http://www.blogjava.net/zeyuphoenix/archive/2010/04/08/317755.html