在论坛搜索了相当多的相关主题,发现大部分实现的都是整列的设置渲染方式!
即指定渲染可以自己创建相关的方法,主要是继承DefaultTableCellRenderer,虽然这里可以实现单个Component的渲染!
但在调用时,90%以上是使用table.getColumnModel().getColumn(列索引参数).setCellRenderer(自定义渲染器),这里面有个重要的缺陷,就是唯独没有对row的位置实现获取,故此请大家指点下,有没有好的办法实现?!我想这个的实现会有相当的意义!
即指定渲染可以自己创建相关的方法,主要是继承DefaultTableCellRenderer,虽然这里可以实现单个Component的渲染!
但在调用时,90%以上是使用table.getColumnModel().getColumn(列索引参数).setCellRenderer(自定义渲染器),这里面有个重要的缺陷,就是唯独没有对row的位置实现获取,故此请大家指点下,有没有好的办法实现?!我想这个的实现会有相当的意义!
解决方案 »
- 关于Float.toString()函数
- javac编译时去哪里找class的
- 请问Timestamp 这个怎么格式化呢?
- [100分]求一个能匹配所有url的正则表达式
- 新手请教,软件版本配置问题
- 编程语言实例大全(JAVA.C.C#.C++).chm怎么打开呀
- 用compareTo 和 equals比较getParameter返回值的用法????
- 高难问题!请教高手!100分。
- 入门级该如何快速上手
- 如何去掉JTable的表格线
- 请问谁能给我个好点的table border的样式和输入框的样式么?
- 请问各位高手 jface tableviewer 中如何获得 当前cell 或者 当前行数列数
楼主【adown】截止到2008-06-25 17:33:48的历史汇总数据(不包括此帖):
发帖数:3 发帖分:70
结贴数:3 结贴分:70
未结数:0 未结分:0
结贴率:100.00% 结分率:100.00%
敬礼!
从这个方法的参数可以看出,它是一个一个cell来渲染的,因此如果要实现行渲染理论上是可以的。我就不贴具体的代码了,LZ可以对row这个参数进行控制,应该就可以达到效果了。另外对于不需要渲染的cell,记住一定要在这个方法里也处理,不然会全部渲染上的!!
import java.awt.Component;
import java.awt.GridLayout;import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;public class TablePanel extends JPanel {
JTable table = null;
MyTableModel model = null;
public TablePanel(){
ininUI();
}
private void ininUI(){
String[] clmnNames = {"aa","bb","cc"};
model = new MyTableModel(clmnNames);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
model.addRow(new Object[]{"1","2","3"});
model.addRow(new Object[]{"11","22","33"});
model.addRow(new Object[]{"111","222","333"});
table.getColumnModel().getColumn(0).setCellRenderer(new MuRender());
table.getColumnModel().getColumn(1).setCellRenderer(new MuRender());
table.getColumnModel().getColumn(2).setCellRenderer(new MuRender());
setLayout(new GridLayout(1,1));
add(table);
}
public class MuRender extends DefaultTableCellRenderer{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
setText((String)value);
if (row % 2 == 1) {
setBackground(Color.RED);
} else {
setBackground(null);
}
return this;
}
}
public class MyTableModel extends DefaultTableModel {
public MyTableModel(String[] clmnNames){
super(clmnNames,0);
}
public boolean isCellEditable(int row, int column){
return false;
} }
}
合乎要求的使用默认的Renderer. 不符合的就带红色底显示!受到3楼的启示,我也创建了一个ColoredCellFieldRenderer,并且使用传参方式构造类package commonModel;import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableCellRenderer;public class ColoredCellFieldRenderer extends JTextField implements TableCellRenderer
{
private int newRow,newColumn;
public ColoredCellFieldRenderer(){}
public ColoredCellFieldRenderer(int row, int column)
{
newRow = row;
newColumn = column;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if(row ==newRow && column == newColumn)
{
setBackground(Color.RED);
}else
{
setBackground(null);
}
setText((value == null) ? "" : value.toString());
return this;
}
}但是在循环检测数据格式是否匹配时,发现它由于获取的是整列的model进行渲染的,在有多行同列的数据上出现错误的话,它会覆盖渲染,结果就会是每列有错的最后一个单元格被使用到改颜色,同列的上层有错数据不会改! 我个人认为根本的症结还是在于它使用的是整列的渲染模式所产生的! 有什么办法可以解决吗?
table代码class TestTable extends JTable {
//key为需要处理单元格的flag
private List<key> specialCellList = new ArrayList<key>(); {
specialCellList.add(key1);
specialCellList.add(key2);
}
public List<key> getSpecialCellList() {
return specialCellList;
}
}
renderer代码public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if(table instanceof TestTable){
TestTable t = (TestTable)table;
if(t.getSpecialCellList().contains(key)){
// paint yourself
return paintComponent;
}
}
return super.getTableCellRendererComponent();
}
可是在同一个table内,假如本身根据数据结构,还实现了其它的render,例如,带button,boolean的等等,由于是一
次性的渲染,结果就把其它的render方式给覆盖了! 这是个相当棘手的问题. 看样子问题又回到了起点! 不知道还
有没有其它好的解决办法?!
如果设置了,那么就用不同的
JTable的源代码:public TableCellRenderer getCellRenderer(int row, int column) {
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null) {
renderer = getDefaultRenderer(getColumnClass(column));
}
return renderer;
}
这样的话,只要你特别设置了renderer(甚至可以给每个单元格设置不同的renderer),那么在刷新的时候就会调用自己设置renderer的刷新方法;
这样在prepareRenderer中,调用方法getTableCellRendererComponent方法之前,可以为renderer刷新做准备,在调用getTableCellRendererComponent方法的时候调用设置的属性进行刷新;
注意,在每次刷新的时候都要进行设置,因为用到同类型renderer的一类单元格用的是同一个renderer,如果不重新设置,那么以后的单元格在刷新时都会用到以前单元格设置过的属性不知道能不能明白
我在各个renderer中把颜色写死了,你可以在prepareRenderer方法中判断是什么renderer,在各个renderer中提供get,set方法,这样,在各个renderer的getTableCellRendererComponent中读取你在renderer设置的属性,进行刷新显示
import java.awt.Color;
import java.awt.Component;import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;public class TableRendererTest extends JFrame { public TableRendererTest() {
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() {
return 10;
} public int getRowCount() {
return 10;
} public Object getValueAt(int row, int col) {
if (row == 0 && col == 0) {
return Boolean.TRUE;
}
return new Integer(row * col);
}
};
JTable table = new TestTable(dataModel);
JScrollPane scrollpane = new JScrollPane(table);
this.getContentPane().add(scrollpane);
} /**
* @param args
*/
public static void main(String[] args) {
TableRendererTest jt = new TableRendererTest();
jt.setVisible(true);
jt.setSize(300, 200);
jt.setDefaultCloseOperation(EXIT_ON_CLOSE);
} private class TestTable extends JTable { public TestTable(TableModel dataModel) {
super(dataModel);
} @Override
public TableCellRenderer getCellRenderer(int row, int column) {
if (row == 0 && column == 0) {
return new BooleanRenderer();
} else if (row == 1 && column == 1) {
return new NumberRenderer();
}
return super.getCellRenderer(row, column);
} @Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
// TODO Auto-generated method stub
return super.prepareRenderer(renderer, row, column);
}
} static class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource {
private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); public BooleanRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
setBorderPainted(true);
} public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (isSelected) {
setForeground(Color.RED);
super.setBackground(Color.YELLOW);
} else {
setForeground(Color.YELLOW);
setBackground(Color.RED);
}
setSelected((value != null && ((Boolean) value).booleanValue())); if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
} else {
setBorder(noFocusBorder);
} return this;
}
} /**
* Default Renderers
*/
static class NumberRenderer extends DefaultTableCellRenderer.UIResource {
public NumberRenderer() {
super();
setHorizontalAlignment(JLabel.RIGHT);
} public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (isSelected) {
setForeground(Color.BLUE);
super.setBackground(Color.GREEN);
} else {
setForeground(Color.GREEN);
setBackground(Color.BLUE);
} setValue(value); if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
} else {
setBorder(noFocusBorder);
} return this;
}
}
}
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;public class CustomTable extends JTable
{
public CustomTable(TableModel model)
{
super(model);
}
@Override
public TableCellRenderer getCellRenderer(int row, int column)
{
TableCellRenderer renderer = null;
renderer = (TableCellRenderer)getValueAt(row, column);//?????
if(null == renderer)
{
renderer = super.getCellRenderer(row, column);
}
return renderer;
}
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
{
return super.prepareRenderer(renderer, row, column);
}
}本想这样可以获得单个cell的渲染,可加载其他类编译时却抛出异常
[code=Jave]
Exception occurred during event dispatching:
java.lang.ClassCastException: java.lang.String
[/code]
难道不可以这样写吗?
怎么这么转?肯定会报ClassCastException
getValueAt得到的是value,不是renderer
可以实现一个单元格一个renderer,就是稍麻烦些
不知道这种方式是不是算获取了单个的cell的渲染器?public TableCellRenderer getCellRenderer(int row, int column)
{
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null && getValueAt(row,column) != null)
{
renderer = getDefaultRenderer(getValueAt(row,column).getClass());
}
if (renderer == null)
{
renderer = getDefaultRenderer(getColumnClass(column));
}
return renderer;
}我总是希望能动态的调用渲染器,而不是预先就指定好? 难道这种思路有问题?
public TableCellRenderer getCellRenderer(int row, int column)
{
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null && getValueAt(row,column) != null)
{
renderer = getDefaultRenderer(getValueAt(row,column).getClass());
}
if (renderer == null)
{
renderer = getDefaultRenderer(getColumnClass(column));
}
return renderer;
}
这段代码由问题,首先: 使用tableColumn.getCellRenderer();的话就注定一列的cell用同类型的renderer...
又不清楚你想实现什么东西了
在初始化table时,根据数据库提取的字段类型首次确定了渲染方式! 此渲染方式与颜色无关。目的是做个数据输入的面板。
输入完成后,由预定义的数据检测方法进行数据格式检测,非法就改变目标cell的底色为红色!反之无变化!这是二次渲染!问题也就是出现在这里。数据是动态的,设置的渲染方式由于获取的是整列的cell,就出现同列cell,只匹配出最后的错误处改颜色,前面的被覆盖了!就是这么个问题?zwgs1985指点下!
首先:table可以支持给每个cell设置渲染方式,但是你是以列为单位进行设置的,那么就只讨论以列为单位的情况
之后:每列用的renderer是一个对象,这是毋庸置疑的,你出现的问题就是因为这个原因引起的
那么,解决这个问题的方式,就是在renderer渲染的时候。
TableCellRenderer中的getTableCellRendererComponent方法是管这事的
那么看看DefaultTableCellRenderer的实现public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) { Color fg = null;
Color bg = null; JTable.DropLocation dropLocation = table.getDropLocation();
if (dropLocation != null
&& !dropLocation.isInsertRow()
&& !dropLocation.isInsertColumn()
&& dropLocation.getRow() == row
&& dropLocation.getColumn() == column) { fg = UIManager.getColor("Table.dropCellForeground");
bg = UIManager.getColor("Table.dropCellBackground"); isSelected = true;
} if (isSelected) {
super.setForeground(fg == null ? table.getSelectionForeground()
: fg);
super.setBackground(bg == null ? table.getSelectionBackground()
: bg);
} else {
super.setForeground(unselectedForeground != null
? unselectedForeground
: table.getForeground());
super.setBackground(unselectedBackground != null
? unselectedBackground
: table.getBackground());
} setFont(table.getFont()); if (hasFocus) {
Border border = null;
if (isSelected) {
border = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
}
if (border == null) {
border = UIManager.getBorder("Table.focusCellHighlightBorder");
}
setBorder(border); if (!isSelected && table.isCellEditable(row, column)) {
Color col;
col = UIManager.getColor("Table.focusCellForeground");
if (col != null) {
super.setForeground(col);
}
col = UIManager.getColor("Table.focusCellBackground");
if (col != null) {
super.setBackground(col);
}
}
} else {
setBorder(getNoFocusBorder());
} setValue(value); return this;
}红色部分是设置显示颜色的,那么就需要该这部分代码,当你判断某个单元格输入错误(或者从DB中读取添加到table中)的时候(你可能能判断是哪个错了,可以得到rowIndex和columnIndex,也就是行列的索引),这样,在table刷新的时候(如果不知道什么时候table刷新,你可以在输入后获得显示DB值之后强制table刷新),就会重新渲染,就会掉到getTableCellRendererComponent方法,而且调用N次(次数与刷新区域的单元格数有关),这样,你在这个方法里判断,如果出错了,你自己设置前景色和背景色,如果没错,就把红色部分的代码写上,如果从DefaultTableCellRenderer继承,那么更省事了,直接调用super就可以了,这样就不会出现设置一个错误cell的背景色,整列都跟着变了。
这个问题和怎么设置renderer(以列为单位设置还是以单元格进行设置)没有关系,只是和刷新有关系,即每个单元格要在什么时候显示什么样的前景色和背景色有关系,也就是改写getTableCellRendererComponent方法,一个单元(在你的代码里可能指的是一列)的单元格在刷新时走的是同一个方法,因为他们用的是同一个renderer,只是走的分支不同,走那个分支需要你自己控制。哎,罗嗦了,你自己看看吧,如果还是不懂,我也没办法啦 :)
super.setForeground(fg == null ? table.getSelectionForeground()
: fg);
super.setBackground(bg == null ? table.getSelectionBackground()
: bg);
} else {
super.setForeground(unselectedForeground != null
? unselectedForeground
: table.getForeground());
super.setBackground(unselectedBackground != null
? unselectedBackground
: table.getBackground());
}
PS:其他属性和颜色一样,都能用同样的方式设置