JRobin的默认字体,不直接中文,要显示中文可以对字体做这样的设置(JRobin1.4)
graphDef.setDefaultFont(new Font("monospaced", Font.PLAIN, 11));
graphDef.setTitleFont(new Font("SansSerif", Font.BOLD, 14));
但是使用RrdGraphDef的line方法,legend的值中含中文时,会发生错位的现象。
public void line( String sourceName, Color color, String legend )
产生的原因为,JRboin把在同一行的legend拼成一个字符串,进行绘图,而把legend前面的颜色方框分别绘制,颜色方框的x位置,是根据legend的length和计算的;英文字符的宽度大概相关于字体高的0.5倍,而汉字宽度则大于这个倍数,作者没有考虑中文的问题;所以计算出来的位置不正确。
简单解法:
//中文字符个数+1,中文比英文字符多出来的宽度
int cnChars = 0;
char[] charArray = tmpStr.toString().toCharArray();
for(int k=0; k<charArray.length;k++){
if ((charArray[k] >= 0x4e00)&&(charArray[k] <= 0x9fbb)){
cnChars++;
}
}
cnChars = (int)(cnChars*0.88);
markerList.addLast( new LegendMarker( (tmpStr.length()+ cnChars) * nfont_width, ((Legend) clist[i]).getColor() ) );
//上面是对源码的修改
tmpStr.append( " " ); // Add 3 spaces where the mark will be
均分各列
LinkedList markerList = new LinkedList();
//add
LinkedList legendList = new LinkedList();
...
if ( clist[i].commentType == Comment.CMT_LEGEND )
{
markerList.addLast( new LegendMarker( tmpStr.length() * nfont_width, ((Legend) clist[i]).getColor() ) );
tmpStr.append( " " ); // Add 3 spaces where the mark will be
}
else {
if ( clist[i].commentType == Comment.CMT_GPRINT )
{
((Gprint) clist[i]).setValue( sources, sourceIndex, valueFormat );
}
markerList.addLast( null );
}
...
ArrayList tknpairs = clist[i].getTokens();
//add
if (tknpairs.size() >0){
String legend = (String) tknpairs.get(0);
if ( clist[i].trimString() )
legendList.addLast(legend.trim());
else
legendList.addLast(legend);
}
...
//替换graphString( g, tmpStr.toString(), posx, posy );到while循环的代码
tmpStr = new StringBuffer("");
drawText = false;
if (!markerList.isEmpty()){
//一行有几个legend
int legendCols = markerList.size();
//两边分别离posx宽的间距,再均分每个legend的间距
int legendWidth = (imgWidth - posx*2)/legendCols;
int currentCol = 0;
// Plot the markers
while ( !markerList.isEmpty() ) {
//绘制颜色方框
LegendMarker lm = (LegendMarker) markerList.removeFirst();
//方框的起始位置
int startPosx = posx + currentCol*legendWidth;
g.setColor( lm.getColor() );
g.fillRect( startPosx, posy - 9, 10, 10 );
g.setColor( normalFontColor );
g.drawRect( startPosx, posy - 9, 10, 10 );
//绘制legend,颜色方框的宽度约为12
String legend = (String) legendList.removeFirst();
graphString( g, legend , startPosx + 12, posy );
currentCol++;
}
}
紧凑排列
//其他代码与均无各列的相同
if (!markerList.isEmpty()){
// Plot the markers
int startPosx = posx;
while ( !markerList.isEmpty() ) {
//绘制颜色方框
LegendMarker lm = (LegendMarker) markerList.removeFirst();
//方框的起始位置
g.setColor( lm.getColor() );
g.fillRect( startPosx, posy - 9, 10, 10 );
g.setColor( normalFontColor );
g.drawRect( startPosx, posy - 9, 10, 10 );
//绘制legend,颜色方框的宽度约为12
String legend = (String) legendList.removeFirst();
int legendStartPosx = startPosx + 12;
graphString( g, legend , legendStartPosx, posy );
char[] charArray = legend.toCharArray();
//中文字符个数+1,中文是英文字符宽度的两倍
int cnChars = 1;
for(int k=0; k<charArray.length;k++){
if ((charArray[k] >= 0x4e00)&&(charArray[k] <= 0x9fbb)){
cnChars++;
}
}
//下一个方框开始的位置为,本legend的起始位置加上legned文字的宽度
startPosx = legendStartPosx + (legend.length()+ cnChars)*nfont_width;
}
}
原代码如下:
private void plotComments( Graphics2D g ) throws RrdException
{
if ( !graphDef.showLegend() ) return;
LinkedList markerList = new LinkedList();
// Position the cursor just below the chart area
int posy = y_offset + chartHeight + CHART_UPADDING + CHART_BPADDING + ( graphDef.showMajorGridX() ? nfont_height : 0 );
int posx = LBORDER_SPACE;
g.setColor( normalFontColor );
g.setFont( normal_font );
Comment[] clist = graphDef.getComments();
StringBuffer tmpStr = new StringBuffer("");
boolean newLine = false;
boolean drawText = false;
for (int i = 0; i < clist.length; i++)
{
if ( clist[i].commentType == Comment.CMT_LEGEND )
{
markerList.addLast( new LegendMarker( tmpStr.length() * nfont_width, ((Legend) clist[i]).getColor() ) );
tmpStr.append( " " ); // Add 3 spaces where the mark will be
}
else if ( clist[i].commentType == Comment.CMT_GPRINT )
((Gprint) clist[i]).setValue( sources, sourceIndex, valueFormat );
ArrayList tknpairs = clist[i].getTokens();
for (int j = 0; j < tknpairs.size(); j++)
{
String str = (String) tknpairs.get(j++);
Byte tkn = (Byte) tknpairs.get(j);
if ( clist[i].trimString() )
tmpStr.append( str.trim() );
else
tmpStr.append( str );
if ( tkn != Comment.TKN_NULL )
{
drawText = true;
if ( tkn == Comment.TKN_ALF ) {
newLine = true;
posx = LBORDER_SPACE;
}
else if ( tkn == Comment.TKN_ARF ) {
newLine = true;
posx = imgWidth - RBORDER_SPACE - (tmpStr.length() * nfont_width);
}
else if ( tkn == Comment.TKN_ACF ) {
newLine = true;
posx = imgWidth / 2 - (tmpStr.length() * nfont_width) / 2;
}
else if ( tkn == Comment.TKN_AL )
posx = LBORDER_SPACE;
else if ( tkn == Comment.TKN_AR )
posx = imgWidth - RBORDER_SPACE - (tmpStr.length() * nfont_width);
else if ( tkn == Comment.TKN_AC )
posx = imgWidth / 2 - (tmpStr.length() * nfont_width) / 2;
}
if ( !newLine && clist[i].addSpacer() )
tmpStr.append( SPACER );
// Plot the string
if ( drawText ) {
graphString( g, tmpStr.toString(), posx, posy );
tmpStr = new StringBuffer("");
drawText = false;
// Plot the markers
while ( !markerList.isEmpty() ) {
LegendMarker lm = (LegendMarker) markerList.removeFirst();
g.setColor( lm.getColor() );
g.fillRect( posx + lm.getXPosition(), posy - 9, 10, 10 );
g.setColor( normalFontColor );
g.drawRect( posx + lm.getXPosition(), posy - 9, 10, 10 );
}
}
if ( newLine ) {
posy += nfont_height + LINE_PADDING;
newLine = false;
}
}
}
if ( tmpStr.length() > 0)
{
posx = LBORDER_SPACE;
graphString( g, tmpStr.toString(), posx, posy );
tmpStr = new StringBuffer("");
drawText = false;
// Plot the markers
while ( !markerList.isEmpty() ) {
LegendMarker lm = (LegendMarker) markerList.removeFirst();
g.setColor( lm.getColor() );
g.fillRect( posx + lm.getXPosition(), posy - 9, 10, 10 );
g.setColor( normalFontColor );
g.drawRect( posx + lm.getXPosition(), posy - 9, 10, 10 );
}
}
}