JFreeCharts畫分時圖

        記錄下畫分時圖的過程。
    

        分時圖繪畫過程也就是折線圖和柱狀圖的結合,這裏還是用CombinedDomainXYPlot這個類來結合畫圖。

        首先畫折線。這裏折線分爲兩條,一條是今日走勢,一條是昨日收盤價。先說數據定義,這裏因爲時間範圍是今天,而每一個點的數據精度到每分鐘,所以在使用TimeSeries時使用Millisecond時間精準到每分鐘。而昨日收盤價是一個不會變的數據,這裏可以用Day,直接定義爲全天範圍就行了。數據定義好後,設置畫圖器XYLineAndShapeRenderer,先設置今日走勢的折線顏色爲White,然後設置昨收顏色爲Red(跟國內大盤樣式保持一致),然後設置setSeriesShapeVisible(false),也就是折線上面的點(小方塊)不顯示。
        
        畫圖器設置完,設置x軸,這裏需要注意的是,國內大盤開盤時間爲9:30-11:30(上午)13:00-15:00(下午),所以這裏時間軸(x軸)自定義時間範圍爲9:30-15:00,11:30-13:00中間間隔時間用SegmentedTimeLine來排除addException(start,end),然後設置時間刻度間隔爲30分鐘。

        y軸這裏需要設置兩條,這裏我只說一條。跟x軸一樣,先關閉自動設置,然後設置好數據範圍。一般情況下這樣就結束了。但是,如上圖所示,畫股票分時圖的時候就會有需要設置y軸多種顏色的情況,然而類提供的setPaint只能統一改變顏色,所以建議寫一個類,去繼承NumberAxis,重寫裏面的drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge)。這個類裏在使用迭代器循環的時候TextUtilities.drawRotatedString這個函數就是寫y軸的顏色。可以在這之前改變G筆的顏色setPaint就行了。至於數據,存放在ValueTick裏。順便提一下,如果要改變y軸數據座標也是在這個函數裏修改就行了。

        然後柱狀圖這裏沒什麼難點,設置數據,設置畫圖器改顏色,設置下刻度顏色,最後用CombinedDomainXYPlot結合在一起畫出來就行了。

貼下數據模型代碼:
public String timeSharingChart(Map<String, String> params){
String path = null;
String data = dataService.getAStockMinData(params);//獲取A股分時數據
params.put("data", data);
logger.info("timeSharingChart : params : " + params);
logger.info("timeSharingChart : data : " + data);
path = timeSharingChartPlant(params);//分時圖製作工廠
return path;
}

/**
* 獲取A股分時數據
*/
public String getAStockMinData(Map<String,String> params){
String secucode = (String)params.get("secucode");
// String market = (String)params.get("market");
// List<Map> dataList = jydbDataServiceImpl.getAIndexOrStockKData(secucode,true, startDate, endDate);
List dataList = getMinQuoteData(secucode);//根據證券代碼、市場獲取當日分時數據
// System.out.println(dataList);
logger.info("getAStockMinData : " + dataList);
Map<String,Object> newDataMap = getNewQuoteData(secucode);//根據證券代碼、市場獲取最新行情數據


Map map = new HashMap();
List quoteMinList = new ArrayList();//封裝日行情數據
List tradVol = new ArrayList();//封裝日交易量數據
String secuabbr = (String)newDataMap.get("secName");
Double openPrice = (Double)newDataMap.get("open");
Double highPrice = (Double)newDataMap.get("high");
Double lowPrice = (Double)newDataMap.get("low");
Double yClose = (Double)newDataMap.get("yClose");
// System.out.println("dataList is :"+dataList);
for(Object data : dataList){
List minData = (List)data;
Object time = minData.get(0);
    Object price = minData.get(1);
    Object tradVolData = minData.get(4);

List minQuote = new ArrayList();//分鐘線數據
List minTradVol = new ArrayList();//分鐘成交量數據
minQuote.add(time);
minQuote.add(price);
quoteMinList.add(minQuote);

minTradVol.add(time);
minTradVol.add(tradVolData);
tradVol.add(minTradVol);
}
map.put("title", secuabbr+"("+secucode+")");
map.put("openPrice", openPrice);
map.put("highPrice", highPrice);
map.put("lowPrice", lowPrice);
map.put("newPrice", quoteMinList);
map.put("yClose", yClose);
map.put("tradVol", tradVol);
return JsonUtil.toJson(map);
}

貼下分時圖代碼:
/**
* 分時圖製作工廠
* @param params
* @return
*/
private String timeSharingChartPlant(Map<String, String> params) {
String path = null;
try{
//獲取繪圖數據
String dJson = params.get("data");
Map<String, Object> datas = (Map<String, Object>)JsonUtil.parse(dJson);
//獲取標題
String title = (String) datas.get("title");


double mLow = Double.valueOf(datas.get("lowPrice").toString());//最低價
double mHigh = Double.valueOf(datas.get("highPrice").toString());//最高價
double yClose = Double.valueOf(datas.get("yClose").toString());//昨日收盤價


TimeSeriesCollection lineSeriesConllection = new TimeSeriesCollection();
TimeSeries serise1 = new TimeSeries("分時數據");
TimeSeries serise2 = new TimeSeries("昨日收盤價");


TimeSeriesCollection barSeriesCollection = new TimeSeriesCollection();//保留成交量數據的集合
TimeSeries serise3 = new TimeSeries("成交量");


//成交量數據
List<List<Object>> tradVol = (List<List<Object>>) datas.get("tradVol");


//分時數據
List<List<Object>> newPrices = (List<List<Object>>) datas.get("newPrice");
Date today = null;//今天


//循環寫入數據
for(int i = 0; i < newPrices.size(); i++){
if(today == null){//記錄今天時間
today = DateFormatUtils.getDate13(newPrices.get(i).get(0).toString());
}
serise1.add(new Millisecond(DateFormatUtils.getDate13(newPrices.get(i).get(0).toString())), Double.valueOf(newPrices.get(i).get(1).toString()));
serise3.add(new Millisecond(DateFormatUtils.getDate13(tradVol.get(i).get(0).toString())),  Double.valueOf(tradVol.get(i).get(1).toString()));
}


serise2.add(new Day(today), yClose);
Date tomorrow = new Date(today.getTime() + 86400000);//明天
serise2.add(new Day(tomorrow), yClose);
//分時圖數據
lineSeriesConllection.addSeries(serise1);
lineSeriesConllection.addSeries(serise2);
//成交量數據
barSeriesCollection.addSeries(serise3);


//設置均線圖畫圖器
XYLineAndShapeRenderer lineAndShapeRenderer = new XYLineAndShapeRenderer();
lineAndShapeRenderer.setBaseItemLabelsVisible(true);
lineAndShapeRenderer.setSeriesShapesVisible(0, false);//設置不顯示數據點模型
lineAndShapeRenderer.setSeriesShapesVisible(1, false);
lineAndShapeRenderer.setSeriesPaint(0, Color.WHITE);//設置均線顏色
lineAndShapeRenderer.setSeriesPaint(1, Color.RED);


//設置k線圖x軸,也就是時間軸
DateAxis domainAxis = new DateAxis();
domainAxis.setAutoRange(false);//設置不採用自動設置時間範圍
//設置時間範圍,注意,最大和最小時間設置時需要+ - 。否則時間刻度無法顯示
Calendar calendar = Calendar.getInstance();
Date da = today;
calendar.setTime(da);
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 29);
calendar.set(Calendar.SECOND, 0);
Date sda = calendar.getTime();
calendar.set(Calendar.HOUR_OF_DAY, 15);
calendar.set(Calendar.MINUTE, 01);
da = calendar.getTime();
domainAxis.setRange(sda, da);//設置時間範圍


DateFormat df = new SimpleDateFormat("HH:mm");
domainAxis.setAutoTickUnitSelection(false);//設置不採用自動選擇刻度值
domainAxis.setTickMarkPosition(DateTickMarkPosition.START);//設置標記的位置
domainAxis.setStandardTickUnits(DateAxis.createStandardDateTickUnits());// 設置標準的時間刻度單位


domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.MINUTE, 30));// 設置時間刻度的間隔
domainAxis.setDateFormatOverride(df);//設置時間格式


SegmentedTimeline timeline = SegmentedTimeline.newFifteenMinuteTimeline();//設置時間線顯示的規則,用這個方法摒除掉週六和週日這些沒有交易的日期


calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 31);
calendar.set(Calendar.SECOND, 0);
sda = calendar.getTime();
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 59);
da = calendar.getTime();


timeline.addException(sda.getTime(), da.getTime());//排除非交易時間段
domainAxis.setTimeline(timeline);


//設置k線圖y軸參數
NumberAxisY1 y1Axis = new NumberAxisY1();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置
y1Axis.setAutoRange(false);//設置不採用自動設置數據範圍
y1Axis.setLabel(String.valueOf(yClose));
y1Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12));
double t = yClose - mLow;
double t1 = mHigh - yClose;
t = Math.abs(t);
t1 = Math.abs(t1);
double range = t1 > t  ? t1 : t;//計算漲跌最大幅度
DecimalFormat df1 = new DecimalFormat("#0.00");
df1.setRoundingMode(RoundingMode.FLOOR);


y1Axis.setRange(Double.valueOf(df1.format(yClose - range)), Double.valueOf(df1.format(yClose + range)));//設置y軸數據範圍
y1Axis.setNumberFormatOverride(df1);
y1Axis.centerRange(yClose);
NumberTickUnit numberTickUnit = new NumberTickUnit(Math.abs(range / 7));
y1Axis.setTickUnit(numberTickUnit);




NumberAxisY2 y2Axis = new NumberAxisY2();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置
y2Axis.setAutoRange(false);//設置不採用自動設置數據範圍
y2Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12));


t = (mLow - yClose) / yClose;
t1 = (mHigh - yClose) / yClose;
t = Math.abs(t);
t1 = Math.abs(t1);
range = t1 > t  ? t1 : t;
y2Axis.setRange(-range, range);//設置y軸數據範圍
y2Axis.setTickLabelPaint(Color.RED);
DecimalFormat df2 = new DecimalFormat("#0.00%");
df2.setRoundingMode(RoundingMode.FLOOR);
y2Axis.setNumberFormatOverride(df2);
NumberTickUnit numberTickUnit2 = new NumberTickUnit(Math.abs(range / 7));
y2Axis.setTickUnit(numberTickUnit2);


//生成畫圖細節 第一個和最後一個參數這裏需要設置爲null,否則畫板加載不同類型的數據時會有類型錯誤異常
//可能是因爲初始化時,構造器內會把統一數據集合設置爲傳參的數據集類型,畫圖器可能也是同樣一個道理
XYPlot plot = new XYPlot(lineSeriesConllection,domainAxis,null,lineAndShapeRenderer);
plot.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色
plot.setDomainGridlinesVisible(false);//不顯示網格
plot.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色
plot.setRangeAxis(0, y1Axis);
plot.setRangeAxis(1, y2Axis);




//設置柱狀圖參數
XYBarRenderer barRenderer = new XYBarRenderer();


barRenderer.setDrawBarOutline(true);//設置顯示邊框線
barRenderer.setBarPainter(new StandardXYBarPainter());//取消漸變效果
barRenderer.setMargin(0.5);//設置柱形圖之間的間隔       
barRenderer.setSeriesPaint(0, Color.YELLOW);//設置柱子內部顏色
barRenderer.setSeriesOutlinePaint(0, Color.YELLOW);//設置柱子邊框顏色
barRenderer.setSeriesVisibleInLegend(false);//設置不顯示legend(數據顏色提示)
barRenderer.setShadowVisible(false);//設置沒有陰影


//設置柱狀圖y軸參數
NumberAxis y3Axis = new NumberAxis();//設置Y軸,爲數值,後面的設置,參考上面的y軸設置
y3Axis.setLabelFont(new Font("微軟雅黑", Font.BOLD, 12));//設置y軸字體
y3Axis.setAutoRange(true);//設置採用自動設置時間範圍
y3Axis.setTickLabelPaint(Color.ORANGE);//設置y軸刻度值顏色


//這裏不設置x軸,x軸參數依照k線圖x軸爲模板
XYPlot plot2 = new XYPlot(barSeriesCollection, null, y3Axis, barRenderer);
plot2.setBackgroundPaint(Color.BLACK);//設置曲線圖背景色
plot2.setDomainGridlinesVisible(false);//不顯示網格
plot2.setRangeGridlinePaint(Color.RED);//設置間距格線顏色爲紅色






//建立一個恰當的聯合圖形區域對象,以x軸爲共享軸
CombinedDomainXYPlot domainXYPlot = new CombinedDomainXYPlot(domainAxis);//
domainXYPlot.add(plot, 2);//添加圖形區域對象,後面的數字是計算這個區域對象應該佔據多大的區域2/3
domainXYPlot.add(plot2, 1);
domainXYPlot.setGap(2);//設置兩個圖形區域對象之間的間隔空間


//生成圖紙
JFreeChart chart = new JFreeChart(title, new Font("微軟雅黑", Font.BOLD, 24), domainXYPlot, true);


calendar.setTimeInMillis(System.currentTimeMillis());
int day = calendar.get(Calendar.DAY_OF_MONTH);
int month = calendar.get(Calendar.MONTH) + 1;
int year = calendar.get(Calendar.YEAR);


String file_path = PropertiesRead.getinstance().getValue("FILE_PATH");
path = year + "-" + month + "-" + day + "/" + Uuid.getUUID() + "timeSharing.png";
file_path = file_path + path;
saveChartAsJPEG(chart, file_path);
} catch (Exception e) {
logger.warn("timeSharingChartPlant:------------Exception--------------");
logger.warn(e);
e.printStackTrace();
}
return path;
}

畫圖:
/**
* 將chart(圖片)存入指定路徑中
* @param chart
* @param path
* @throws IOException
*/
private void saveChartAsJPEG(JFreeChart chart, String path) throws IOException{
int width = Integer.valueOf(PropertiesRead.getinstance().getValue("IMG_WIDTH"));
int height = Integer.valueOf(PropertiesRead.getinstance().getValue("IMG_HEIGHT"));


String fileDir = path.substring(0, path.lastIndexOf("/"));
// 創建文件輸出流
File fos_jpg = new File(fileDir);
fos_jpg.mkdirs();//創建文件抽象路徑
fos_jpg = new File(path);//創建圖片文件


// 輸出到哪個輸出流
ChartUtilities.saveChartAsJPEG(fos_jpg, chart, // 統計圖表對象
width, // 寬
height// 高
);
}

/**
* 此內部類專門爲分時圖提供,已解決分時圖y軸數據刻度無法顯示多種顏色的情況
* @author t
*
*/
private class NumberAxisY2 extends NumberAxis{
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge)
{
AxisState state = new AxisState(cursor);
if (isAxisLineVisible()) {
drawAxisLine(g2, cursor, dataArea, edge);
}


List ticks = refreshTicks(g2, state, dataArea, edge);
state.setTicks(ticks);
g2.setFont(getTickLabelFont());
Iterator iterator = ticks.iterator();
while (iterator.hasNext()) {
ValueTick tick = (ValueTick)iterator.next();
if (isTickLabelsVisible()) {
if(tick.getValue() > 0){
g2.setPaint(Color.RED);
} else if(tick.getValue() == 0){
g2.setPaint(Color.GRAY);
} else {
g2.setPaint(Color.GREEN);
}


float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
TextUtilities.drawRotatedString(tick.getText(), g2, anchorPoint[0], anchorPoint[1], tick.getTextAnchor(), tick.getAngle(), tick.getRotationAnchor());
}


if (((isTickMarksVisible()) && (tick.getTickType().equals(TickType.MAJOR))) || ((isMinorTickMarksVisible()) && (tick.getTickType().equals(TickType.MINOR))))
{
double ol = getTickMarkOutsideLength();


double il = getTickMarkInsideLength();


float xx = (float)valueToJava2D(tick.getValue(), dataArea, edge);


Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}


}


double used = 0.0D;
if (isTickLabelsVisible()) {
if (edge == RectangleEdge.LEFT) {
used += findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorLeft(used);
}
else if (edge == RectangleEdge.RIGHT) {
used = findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorRight(used);
}
else if (edge == RectangleEdge.TOP) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorUp(used);
}
else if (edge == RectangleEdge.BOTTOM) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorDown(used);
}
}


return state;
}
}


/**
* 此內部類專門爲分時圖提供,以解決分時圖y軸無法以昨日收盤價爲中心來描寫刻度數據的問題
* @author t 
*
*/
private class NumberAxisY1 extends NumberAxis{
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge)
{
AxisState state = new AxisState(cursor);
if (isAxisLineVisible()) {
drawAxisLine(g2, cursor, dataArea, edge);
}


List ticks = refreshTicks(g2, state, dataArea, edge);
//昨日收盤價
double yClose = Double.valueOf(getLabel());
//獲取兩個價位
NumberTick tick1 = (NumberTick) ticks.get(0);
NumberTick tick2 = (NumberTick) ticks.get(1);


//獲取價位差值,而每個差值都是約等於
Double tick1Val = Double.valueOf(tick1.getText());
Double tick2Val = Double.valueOf(tick2.getText());
Double range = tick2Val - tick1Val;


//重置ticks集合,將昨日收盤價置於中間刻度,因設置刻度時與國內股票分時圖刻度規則有差異,例:國內爲上下7個刻度,加上中間的昨日收盤價,一起爲15個刻度
//而這裏設置7個刻度則沒有寫入昨日收盤價的中間刻度,所以這裏重置ticks集合,長度爲ticks集合size + 1,中間爲昨日收盤價,然後以價位差值從中間開始往上
//下兩個方向推,則可以得到合適的且平均的刻度價位
int ticksSize = 14;
NumberTick[] nticks = new NumberTick[ticksSize + 1];
NumberTick tickCenter = new NumberTick(yClose, String.valueOf(yClose), tick1.getTextAnchor(), tick1.getRotationAnchor(), tick1.getAngle());
//定位中間刻度,昨日收盤價
nticks[ticksSize / 2] = tickCenter;
double t = yClose;
//計算向下的價位,並寫入集合中
for(int i = ticksSize / 2 - 1; i >= 0; i--){
t = t - range;
NumberTick tickF = new NumberTick(t, String.valueOf(t), tick1.getTextAnchor(), tick1.getRotationAnchor(), tick1.getAngle());
nticks[i] = tickF;
}
t = yClose;
//計算向上的價位,並寫入集合中
for(int i = ticksSize / 2 + 1; i < ticksSize + 1; i++){
t = t + range;
NumberTick tickF = new NumberTick(t, String.valueOf(t), tick1.getTextAnchor(), tick1.getRotationAnchor(), tick1.getAngle());
nticks[i] = tickF;
}
ticks = new ArrayList();
for(NumberTick ti : nticks){
ticks.add(ti);
}
state.setTicks(ticks);
g2.setFont(getTickLabelFont());
Iterator iterator = ticks.iterator();


while (iterator.hasNext()) {
ValueTick tick = (ValueTick)iterator.next();
double tickValue = Double.valueOf(tick.getText());
float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
if (isTickLabelsVisible()) {
if(tickValue > yClose){
g2.setPaint(Color.RED);
} else if(tickValue == yClose){
g2.setPaint(Color.GRAY);
} else {
g2.setPaint(Color.GREEN);
}
DecimalFormat df1 = new DecimalFormat("#0.00");


TextUtilities.drawRotatedString(df1.format(tickValue), g2, anchorPoint[0], anchorPoint[1], tick.getTextAnchor(), tick.getAngle(), tick.getRotationAnchor());
}


if (((isTickMarksVisible()) && (tick.getTickType().equals(TickType.MAJOR))) || ((isMinorTickMarksVisible()) && (tick.getTickType().equals(TickType.MINOR))))
{
double ol = getTickMarkOutsideLength();


double il = getTickMarkInsideLength();


float xx = (float)valueToJava2D(tick.getValue(), dataArea, edge);


Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}


}


double used = 0.0D;
if (isTickLabelsVisible()) {
if (edge == RectangleEdge.LEFT) {
used += findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorLeft(used);
}
else if (edge == RectangleEdge.RIGHT) {
used = findMaximumTickLabelWidth(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorRight(used);
}
else if (edge == RectangleEdge.TOP) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorUp(used);
}
else if (edge == RectangleEdge.BOTTOM) {
used = findMaximumTickLabelHeight(ticks, g2, plotArea, isVerticalTickLabels());


state.cursorDown(used);
}
}


return state;
}


@Override
protected AxisState drawLabel(String label, Graphics2D g2, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge, AxisState state) {


AffineTransform t;
Shape rotatedLabelBounds;
double labelx;
double labely;
if (state == null) {
throw new IllegalArgumentException("Null 'state' argument.");
}
//此y軸不提供y軸數據標題
label = "";
if ((label == null) || (label.equals(""))) {
return state;
}


Font font = getLabelFont();
RectangleInsets insets = getLabelInsets();
g2.setFont(font);
g2.setPaint(getLabelPaint());
FontMetrics fm = g2.getFontMetrics();
Rectangle2D labelBounds = TextUtilities.getTextBounds(label, g2, fm);


if (edge == RectangleEdge.TOP) {
t = AffineTransform.getRotateInstance(getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY());


rotatedLabelBounds = t.createTransformedShape(labelBounds);
labelBounds = rotatedLabelBounds.getBounds2D();
labelx = dataArea.getCenterX();
labely = state.getCursor() - insets.getBottom() - (labelBounds.getHeight() / 2.0D);


TextUtilities.drawRotatedString(label, g2, (float)labelx, (float)labely, TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER);


state.cursorUp(insets.getTop() + labelBounds.getHeight() + insets.getBottom());
}
else if (edge == RectangleEdge.BOTTOM) {
t = AffineTransform.getRotateInstance(getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY());


rotatedLabelBounds = t.createTransformedShape(labelBounds);
labelBounds = rotatedLabelBounds.getBounds2D();
labelx = dataArea.getCenterX();
labely = state.getCursor() + insets.getTop() + labelBounds.getHeight() / 2.0D;


TextUtilities.drawRotatedString(label, g2, (float)labelx, (float)labely, TextAnchor.CENTER, getLabelAngle(), TextAnchor.CENTER);


state.cursorDown(insets.getTop() + labelBounds.getHeight() + insets.getBottom());
}
else if (edge == RectangleEdge.LEFT) {
t = AffineTransform.getRotateInstance(getLabelAngle() - 1.570796326794897D, labelBounds.getCenterX(), labelBounds.getCenterY());


rotatedLabelBounds = t.createTransformedShape(labelBounds);
labelBounds = rotatedLabelBounds.getBounds2D();
labelx = state.getCursor() - insets.getRight() - (labelBounds.getWidth() / 2.0D);


labely = dataArea.getCenterY();
TextUtilities.drawRotatedString(label, g2, (float)labelx, (float)labely, TextAnchor.CENTER, getLabelAngle() - 1.570796326794897D, TextAnchor.CENTER);


state.cursorLeft(insets.getLeft() + labelBounds.getWidth() + insets.getRight());
}
else if (edge == RectangleEdge.RIGHT)
{
t = AffineTransform.getRotateInstance(getLabelAngle() + 1.570796326794897D, labelBounds.getCenterX(), labelBounds.getCenterY());


rotatedLabelBounds = t.createTransformedShape(labelBounds);
labelBounds = rotatedLabelBounds.getBounds2D();
labelx = state.getCursor() + insets.getLeft() + labelBounds.getWidth() / 2.0D;


labely = dataArea.getY() + dataArea.getHeight() / 2.0D;
TextUtilities.drawRotatedString(label, g2, (float)labelx, (float)labely, TextAnchor.CENTER, getLabelAngle() + 1.570796326794897D, TextAnchor.CENTER);


state.cursorRight(insets.getLeft() + labelBounds.getWidth() + insets.getRight());
}


return state;
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章