为DataGride单元格添加背景色
英文原文:《Coloring the Background of Cells》
原文地址:http://weblogs.macromedia.com/pent/archives/2007/02/coloring_the_ba.cfm
原文作者:Peter Ent
译者:Dreamer。
引用地址:http://www.zhuoqun.net/trackback.asp?tbID=405
Flex中的DataGrid可能是最经常用到的一个控件(除了Label和Button)。一个总是被提出的问题是:“我如何才能给单元格添加上背景色?”我将会回答这个问题,而且还会演示如何为行和列添加背景色。
单元格背景色
你需要一个itemRenderer来改变特定单元格的背景色。一个itemRenderer既可以应用到一个DataGrid的所有单元格(在<mx:DataGrid>标签中定义的时候),也可以应用到某一列的所有单元格(在<mx:DataGridColumn>标签中定义的时候)。
这里有一个给Year这一列得单元格添加了背景色的例子。那些值小于2000的背景为蓝色,而值大于2000的背景为绿色。
![](http://www.zhuoqun.net/attachments/month_0702/k20072412517.JPG)
改变一个单元格的背景颜色很简单,只需要覆写updateDisplayList函数来画一个填充矩形就行了。如果你只是想更改一个单元格的背景色,你可以创建一个扩展自mx.controls.Label的itemRenderer。下面的代码就是一个基于Label的itemRenderer,它使得year的值小于2000的单元格的背景色为蓝色,否则为绿色。
程序代码
列的背景色
如果你想要将某一列中的所有单元格都设置背景色的话,就不需要创建一个itemRenderer了。DataGridColumn类使用了backgroundColor样式并且将其均一地应用到某一列。实际上,这个背景是一个真正的背景——它和单元格一点关系没有,因为颜色被应用到单元格的下面。
程序代码
Year这一列得背景色将一致为红色。单元格高亮和选中的颜色被应用到背景的上面,所以这些将可以被看到。但是所有的行的颜色,比如DataGird的行的间隔颜色,将不会被看到,这是因为列的backgroundColor是一致的并且在行的颜色的上面。这里有一个为列添加颜色的例子:
![](http://www.zhuoqun.net/attachments/month_0702/d20072412735.jpg)
列的背景的透明度
很不幸,DataGridColumn并没有使用backgroundAlpha样式而且颜色总是一致的。但是如果你想要某一列的背景有点透明的话,这点是很容易做到的。
你需要做的第一件事情就是创建一个扩展自DataGrid的类。你既可以创建一个MXML文件(使用DataGrid作为它的根标签)也可以创建一个扩展自DataGrid的ActionScript类。
在你创建的类中,覆写drawColumnBackground函数来调整透明度:
程序代码
这个函数调用父类的函数来做所有复杂的工作,然后将背景的透明度设置为0.5。现在颜色将会变成半透明的,而且会显示出行的间隔颜色,如下图所示:
![](http://www.zhuoqun.net/attachments/month_0702/u20072412935.jpg)
为了让这个类变得更容易重用,可以为透明度的值添加一个公有变量。将
程序代码
添加到类中,然后更改函数:
程序代码
默认的功能就是和DataGrid的功能一样并添加一个一致的背景颜色。如果要使背景透明一点的话:
程序代码
这里假设你将创建的类命名为ColoredBackgroundDataGrid,上面的MXML标签中将透明度设置为0.3会使其更加透明。现在你就有了一个可以重用的类。
行的背景色
除了如何为特定单元格添加背景色的问题,如何为一整行添加背景色可能是最经常被提出的与颜色有关的DataGrid问题了。下面有一个例子,它根据行中的数据为某些行添加了背景色。
![](http://www.zhuoqun.net/attachments/month_0702/u200724121147.jpg)
为一行添加背景色诗通过覆写drawRowBackground函数来实现的:
程序代码
不管你传送给函数的颜色值是多少,这个例子中的行将拥有一致的红色背景。当然,我们的目标是根据给定行中的数据来确定是什么颜色。所以函数更改为:
程序代码
现在颜色是由每一行的year数据域中的值决定的:小于2000的是橙色,大于等于2000的是白色,没有数据项的是绿色。
dataIndex可能比dataProvider中元素的个数的值要大。这是因为行数可能比数据要多。例如,如果你可以看到DataGrid中有十行但是在dataProvider中只有6条记录,就会有4行没有数据,所以数据项可能会是null。
这个例子中的颜色是硬编码的而且由一个特定的数据域所决定,这个数据域同样是硬编码的。你可以向类中添加一个颜色函数使其可以重用,这个函数就像是列的labelFunction,只不过它会返回一个颜色值而不是一个字符串。为了达到这个目的,要添加另一个公有变量:
程序代码
注意这个变量的类型是Function。你可以在drawRowBackground函数中使用它:
程序代码
现在drawRowBackground将会先查看是否定义了rowColorFunction,如果没有定义, 标准颜色就会被使用。如果定义了rowColorFunction,它就会被调用并传入参数,而且它将会返回一种颜色。
这里有一个例子,结果如上面的图所示:
程序代码
硬编码的drawRowFunction中使用的逻辑现在被放在主程序的一个函数中。这意味着你可以在任何可以正常使用DataGrid的地方使用ColoredBackgroundDataGrid。
列的高级背景色
一个和rowColorFunction相似的函数可以被应用到列上。这里展示了一种可能:
![](http://www.zhuoqun.net/attachments/month_0702/q200724121530.jpg)
考虑一下这个columnBackgroundFunction:
程序代码
这个函数在columnShape(见上图)中画了一个渐变填充的矩形。使用Shape可以允许轻量级的图形作为列的背景;你也可以对行使用同样的技巧。
在DataGrid中对drawColumnBackground做如下更改:
程序代码
正如你所看到的那样,这一个比较复杂,因为必须创建一个Shape,然后添加到Sprite,并且要计算出位置和维数。
总结
虽然DataGrid确实提供了为列添加背景色的功能,但是你不能更改列的背景透明度。你也不需要使用itemRenderer来给某一行(或某一列)添加背景色。你只需要创建一个扩展自DataGrid的类并覆写一些函数,就可以很容易地为行或列(或二者同时)添加背景色,而且你可以使这个类变得更为通用。
当你考虑DataGrid的背景的可能性时,高级的columnBackgroundFunction应该就“可以做到什么程度”给了你一些想法。
原文地址:http://weblogs.macromedia.com/pent/archives/2007/02/coloring_the_ba.cfm
原文作者:Peter Ent
译者:Dreamer。
引用地址:http://www.zhuoqun.net/trackback.asp?tbID=405
为单元格添加背景色
Flex中的DataGrid可能是最经常用到的一个控件(除了Label和Button)。一个总是被提出的问题是:“我如何才能给单元格添加上背景色?”我将会回答这个问题,而且还会演示如何为行和列添加背景色。
单元格背景色
你需要一个itemRenderer来改变特定单元格的背景色。一个itemRenderer既可以应用到一个DataGrid的所有单元格(在<mx:DataGrid>标签中定义的时候),也可以应用到某一列的所有单元格(在<mx:DataGridColumn>标签中定义的时候)。
这里有一个给Year这一列得单元格添加了背景色的例子。那些值小于2000的背景为蓝色,而值大于2000的背景为绿色。
改变一个单元格的背景颜色很简单,只需要覆写updateDisplayList函数来画一个填充矩形就行了。如果你只是想更改一个单元格的背景色,你可以创建一个扩展自mx.controls.Label的itemRenderer。下面的代码就是一个基于Label的itemRenderer,它使得year的值小于2000的单元格的背景色为蓝色,否则为绿色。
![程序代码](http://www.zhuoqun.net/images/code.gif)
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var g:Graphics = graphics;
g.clear();
g.beginFill( data.year < 2000 ? 0x0000FF : 0x00FF00 );
g.drawRect(0,0,unscaledWidth,unscaledHeight);
g.endFill();
}
]]></mx:Script>
</mx:Label>
<mx:Script><![CDATA[
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var g:Graphics = graphics;
g.clear();
g.beginFill( data.year < 2000 ? 0x0000FF : 0x00FF00 );
g.drawRect(0,0,unscaledWidth,unscaledHeight);
g.endFill();
}
]]></mx:Script>
</mx:Label>
列的背景色
如果你想要将某一列中的所有单元格都设置背景色的话,就不需要创建一个itemRenderer了。DataGridColumn类使用了backgroundColor样式并且将其均一地应用到某一列。实际上,这个背景是一个真正的背景——它和单元格一点关系没有,因为颜色被应用到单元格的下面。
![程序代码](http://www.zhuoqun.net/images/code.gif)
<mx:DataGridColumn headerText="Make" dataField="col1" backgroundColor="red" />
Year这一列得背景色将一致为红色。单元格高亮和选中的颜色被应用到背景的上面,所以这些将可以被看到。但是所有的行的颜色,比如DataGird的行的间隔颜色,将不会被看到,这是因为列的backgroundColor是一致的并且在行的颜色的上面。这里有一个为列添加颜色的例子:
![](http://www.zhuoqun.net/attachments/month_0702/d20072412735.jpg)
列的背景的透明度
很不幸,DataGridColumn并没有使用backgroundAlpha样式而且颜色总是一致的。但是如果你想要某一列的背景有点透明的话,这点是很容易做到的。
你需要做的第一件事情就是创建一个扩展自DataGrid的类。你既可以创建一个MXML文件(使用DataGrid作为它的根标签)也可以创建一个扩展自DataGrid的ActionScript类。
在你创建的类中,覆写drawColumnBackground函数来调整透明度:
![程序代码](http://www.zhuoqun.net/images/code.gif)
override protected function drawColumnBackground(s:Sprite, columnIndex:int, color:uint,
column:DataGridColumn):void
{
super.drawColumnBackground(s,columnIndex,color,column);
var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
if( background ) {
background.alpha = 0.5;
}
}
column:DataGridColumn):void
{
super.drawColumnBackground(s,columnIndex,color,column);
var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
if( background ) {
background.alpha = 0.5;
}
}
这个函数调用父类的函数来做所有复杂的工作,然后将背景的透明度设置为0.5。现在颜色将会变成半透明的,而且会显示出行的间隔颜色,如下图所示:
![](http://www.zhuoqun.net/attachments/month_0702/u20072412935.jpg)
为了让这个类变得更容易重用,可以为透明度的值添加一个公有变量。将
![程序代码](http://www.zhuoqun.net/images/code.gif)
public var columnBackgroundAlpha:Number = 1;
添加到类中,然后更改函数:
![程序代码](http://www.zhuoqun.net/images/code.gif)
backgroundAlpha = columnBackgroundAlpha;
默认的功能就是和DataGrid的功能一样并添加一个一致的背景颜色。如果要使背景透明一点的话:
![程序代码](http://www.zhuoqun.net/images/code.gif)
<local:ColoredBackgroundDataGrid columnBackgroundAlpha="0.3" ... >
这里假设你将创建的类命名为ColoredBackgroundDataGrid,上面的MXML标签中将透明度设置为0.3会使其更加透明。现在你就有了一个可以重用的类。
行的背景色
除了如何为特定单元格添加背景色的问题,如何为一整行添加背景色可能是最经常被提出的与颜色有关的DataGrid问题了。下面有一个例子,它根据行中的数据为某些行添加了背景色。
![](http://www.zhuoqun.net/attachments/month_0702/u200724121147.jpg)
为一行添加背景色诗通过覆写drawRowBackground函数来实现的:
![程序代码](http://www.zhuoqun.net/images/code.gif)
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
dataIndex:int):void
{
color = 0xFF0000;
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
dataIndex:int):void
{
color = 0xFF0000;
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
不管你传送给函数的颜色值是多少,这个例子中的行将拥有一致的红色背景。当然,我们的目标是根据给定行中的数据来确定是什么颜色。所以函数更改为:
![程序代码](http://www.zhuoqun.net/images/code.gif)
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
dataIndex:int):void
{
var dp:ArrayCollection = dataProvider as ArrayCollection;
var item:Object;
if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
if( item != null && item.year < 20000 ) color = 0xFF8800;
else if( item != null && item.year>= 2000 ) color = 0xFFFFFF;
else color = 0x00CC00;
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
dataIndex:int):void
{
var dp:ArrayCollection = dataProvider as ArrayCollection;
var item:Object;
if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
if( item != null && item.year < 20000 ) color = 0xFF8800;
else if( item != null && item.year>= 2000 ) color = 0xFFFFFF;
else color = 0x00CC00;
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
现在颜色是由每一行的year数据域中的值决定的:小于2000的是橙色,大于等于2000的是白色,没有数据项的是绿色。
dataIndex可能比dataProvider中元素的个数的值要大。这是因为行数可能比数据要多。例如,如果你可以看到DataGrid中有十行但是在dataProvider中只有6条记录,就会有4行没有数据,所以数据项可能会是null。
这个例子中的颜色是硬编码的而且由一个特定的数据域所决定,这个数据域同样是硬编码的。你可以向类中添加一个颜色函数使其可以重用,这个函数就像是列的labelFunction,只不过它会返回一个颜色值而不是一个字符串。为了达到这个目的,要添加另一个公有变量:
![程序代码](http://www.zhuoqun.net/images/code.gif)
public var rowColorFunction:Function;
注意这个变量的类型是Function。你可以在drawRowBackground函数中使用它:
![程序代码](http://www.zhuoqun.net/images/code.gif)
override protected function drawRowBackground(s:Sprite, rowIndex:int, y:Number, height:Number, color:uint,
dataIndex:int):void
{
if( rowColorFunction != null ) {
var dp:ArrayCollection = dataProvider as ArrayCollection;
var item:Object;
if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
color = rowColorFunction( item, rowIndex, dataIndex, color );
}
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
dataIndex:int):void
{
if( rowColorFunction != null ) {
var dp:ArrayCollection = dataProvider as ArrayCollection;
var item:Object;
if( dataIndex < dp.length ) item = dp.getItemAt(dataIndex);
color = rowColorFunction( item, rowIndex, dataIndex, color );
}
super.drawRowBackground(s,rowIndex,y,height,color,dataIndex);
}
现在drawRowBackground将会先查看是否定义了rowColorFunction,如果没有定义, 标准颜色就会被使用。如果定义了rowColorFunction,它就会被调用并传入参数,而且它将会返回一种颜色。
这里有一个例子,结果如上面的图所示:
![程序代码](http://www.zhuoqun.net/images/code.gif)
<local:ColoredBackgroundDataGrid rowColorFunction="determineColor" ... >
private function rowColorFunction( item:Object, rowIndex:int, dataIndex:int, oldColor:uint ) : uint
{
if( item == null ) return 0x00CC00; // green are empty rows
if( item.year< 2000 ) return 0xFFCC00;
else if( item.year >= 2000 ) return 0xFFFFFF;
}
private function rowColorFunction( item:Object, rowIndex:int, dataIndex:int, oldColor:uint ) : uint
{
if( item == null ) return 0x00CC00; // green are empty rows
if( item.year< 2000 ) return 0xFFCC00;
else if( item.year >= 2000 ) return 0xFFFFFF;
}
硬编码的drawRowFunction中使用的逻辑现在被放在主程序的一个函数中。这意味着你可以在任何可以正常使用DataGrid的地方使用ColoredBackgroundDataGrid。
列的高级背景色
一个和rowColorFunction相似的函数可以被应用到列上。这里展示了一种可能:
![](http://www.zhuoqun.net/attachments/month_0702/q200724121530.jpg)
考虑一下这个columnBackgroundFunction:
![程序代码](http://www.zhuoqun.net/images/code.gif)
private function columnGradient(column:DataGridColumn, columnIndex:int, columnShape:Shape,
x:Number, y:Number, width:Number, height:Number) : void
{
var m:Matrix = new Matrix();
m.createGradientBox(width,height,0,x,0);
columnShape.graphics.clear();
columnShape.graphics.beginGradientFill(GradientType.LINEAR,[0xFFFF00,0xFF0000],[1,1],[0,255],m);
columnShape.graphics.drawRect(x,y,width,height);
columnShape.graphics.endFill();
}
x:Number, y:Number, width:Number, height:Number) : void
{
var m:Matrix = new Matrix();
m.createGradientBox(width,height,0,x,0);
columnShape.graphics.clear();
columnShape.graphics.beginGradientFill(GradientType.LINEAR,[0xFFFF00,0xFF0000],[1,1],[0,255],m);
columnShape.graphics.drawRect(x,y,width,height);
columnShape.graphics.endFill();
}
这个函数在columnShape(见上图)中画了一个渐变填充的矩形。使用Shape可以允许轻量级的图形作为列的背景;你也可以对行使用同样的技巧。
在DataGrid中对drawColumnBackground做如下更改:
![程序代码](http://www.zhuoqun.net/images/code.gif)
override protected function drawColumnBackground(s:Sprite, columnIndex:int, color:uint,
column:DataGridColumn):void
{
super.drawColumnBackground(s,columnIndex,color,column);
var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
if( background ) {
background.alpha = columnBackgroundAlpha;
}
if( columnBackgroundFunction != null ) {
var columnShape:Shape = Shape(s.getChildByName("lines"+columnIndex.toString()));
if( columnShape == null ) {
columnShape = new Shape();
columnShape.name = "lines"+columnIndex;
s.addChild(columnShape);
}
var lastRow:Object = rowInfo[listItems.length - 1];
var xx:Number = listItems[0][columnIndex].x;
var yy:Number = rowInfo[0].y;
var ww:Number = listItems[0][columnIndex].width;
if (this.headerHeight > 0)
yy += rowInfo[0].height;
var hh:Number = Math.min(lastRow.y + lastRow.height,
listContent.height - yy);
columnBackgroundFunction( column, columnIndex, columnShape, xx, yy, ww, hh );
}
}
column:DataGridColumn):void
{
super.drawColumnBackground(s,columnIndex,color,column);
var background:Shape = Shape(s.getChildByName(columnIndex.toString()));
if( background ) {
background.alpha = columnBackgroundAlpha;
}
if( columnBackgroundFunction != null ) {
var columnShape:Shape = Shape(s.getChildByName("lines"+columnIndex.toString()));
if( columnShape == null ) {
columnShape = new Shape();
columnShape.name = "lines"+columnIndex;
s.addChild(columnShape);
}
var lastRow:Object = rowInfo[listItems.length - 1];
var xx:Number = listItems[0][columnIndex].x;
var yy:Number = rowInfo[0].y;
var ww:Number = listItems[0][columnIndex].width;
if (this.headerHeight > 0)
yy += rowInfo[0].height;
var hh:Number = Math.min(lastRow.y + lastRow.height,
listContent.height - yy);
columnBackgroundFunction( column, columnIndex, columnShape, xx, yy, ww, hh );
}
}
正如你所看到的那样,这一个比较复杂,因为必须创建一个Shape,然后添加到Sprite,并且要计算出位置和维数。
总结
虽然DataGrid确实提供了为列添加背景色的功能,但是你不能更改列的背景透明度。你也不需要使用itemRenderer来给某一行(或某一列)添加背景色。你只需要创建一个扩展自DataGrid的类并覆写一些函数,就可以很容易地为行或列(或二者同时)添加背景色,而且你可以使这个类变得更为通用。
当你考虑DataGrid的背景的可能性时,高级的columnBackgroundFunction应该就“可以做到什么程度”给了你一些想法。