duilib控件

BarPlot

首先在XML文件中添加一个hostview: PTGraphHostingView name="IDC_PLOTHOSTVIEW_BY"

CPTGraphHostingView* host;
double yMax;
CString plothost;
host = (CPTGraphHostingView*)DuiGetDlgItem(_T("IDC_PLOTHOSTVIEW_BY"));
plothost = _T("benyue");
yMax = Upper(m_byYMax);
CPTLegend* legend;
CPTPlotSymbol symbol;
CPTXYGraph* graph;

一个hostview中需要先设置一个画布CPTXYGraph对象,BarPlot只能添加到这个画布对象中 ,当一个界面中有多个hostview时,这些hostview中的BarPlot需要知道自己属于哪个hostview,字符串变量plothost就是用来标识所处的hostview的。

由于BarPlot需要绘制坐标轴,所以首先需要知道Y轴绘制的逻辑值的最大值,yMax就是这个最大值。

graph = (CPTXYGraph*)host->GetHostedGraph();
if (graph == NULL)
{
graph = new CPTXYGraph;
host->SetHostedGraph(graph);
}
host->Reset();

CPTXYGraph是支持XY轴坐标系的画布,确保只设置一次,因为这段代码可能会多次执行,所以先判断一下是否为NUL。

host->Reset()这行代码也是考虑到这段代码可能被多次执行的原因,Reset()函数会把自己的画布里的坐标轴的刻度值清空,否则多次设置坐标轴会导致坐标刻度重复增加。

legend = host->Legend();
legend->align = CPTLegendAlignTop;


取得图例,并设置图例放在顶部。

graph->originPoint.x = 70;
graph->originPoint.y = 50;

设置画布中坐标轴的原点

如图,灰色为画布,坐标轴原点距离画布原点横向距离70像素,垂直距离50像素。

CPTTextStyle xLabelTextStyle;//X轴坐标标签字体
xLabelTextStyle.fontSize = 12;
xLabelTextStyle.color = RGB(20, 20, 20);
CPTAxis *x = graph->AxisSet()->xAxis();//X轴
x->majorTickLength = 5;//主刻度长度,按像素
x->minorTicksPerInterval = 1;//主刻度之间几个细分刻度
x->minorTickLength = 2;//细分刻度的长度,按像素
x->tickDirection = CPTSignNegative;//刻度方向,CPTSignNegative代表从X坐标轴向下绘制,CPTSignPositive代表从X坐标轴向上绘制
x->labelTextStyle = xLabelTextStyle;

以上为X轴刻度及标签的基本设置。

int year,month,days;
GetCurrentMonth(year, month);//本月
days=GetDays(year, month);//本月的天数
CString s;
CString location;
CPTAxisLabel* label;
for (int i = 0; i < days; i++)
{
location.Format(_T("%d"), i + 1);
if (i % 3 == 1 || i==days-1)
s.Format(_T("%d日"), i + 1);
else
s.Empty();
label = x->NewLabel(location, s);
label->offset = -1 * (x->majorTickLength + x->labelOffset);
label->rotation = -45 * PI / 180;
x->AddMajorTickLocations(location);
}

以上为添加X轴主刻度,location为一个字符串,与刻度是一一对应的关系,不可重复,需要几个刻度就添加几个location

CPTTextStyle yLabelTextStyle;//Y轴坐标标签字体
yLabelTextStyle.fontSize = 18;
yLabelTextStyle.color = RGB(20, 20, 20);
CPTAxis *y = graph->AxisSet()->yAxis();//Y轴
y->labelTextStyle = yLabelTextStyle;
y->majorTickLength = 3;
y->minorTicksPerInterval = 1;
y->minorTickLength = 2;
y->tickDirection = CPTSignPositive;

以上为Y轴刻度及标签的基本设置。

int majorIncrement = (int)(yMax / 5);
int minorIncrement = majorIncrement / 2;
if (majorIncrement == 0)
majorIncrement = 1;
if (minorIncrement == 0)
minorIncrement = 1;

以上代码按Y值的最大值均分成5个刻度,会按按主刻度绘制5条平行于X轴的直线,再将主刻度一分为二为细分刻度。

for (int j = minorIncrement; j <= yMax; j += minorIncrement)
{
location.Format(_T("%d"), j);
int mod = j%majorIncrement;
if (mod == 0)
{
s.Format(_T("%d"), j);
label = y->NewLabel(location, s);
label->offset = -1 * (y->majorTickLength + y->labelOffset);
y->AddMajorTickLocations(location);//添加主刻度
}
else
{
y->AddMinorTickLocations(location);//添加细分刻度
}
}

以上代码添加刻度值,注意,Y轴刻度的location必须是对应的刻度值。

CPTBarPlot* plot;
CPTLineStyle ls;
ls.lineWidth = 9;
for (int i = 0; i<2; i++)
{
plot = new CPTBarPlot;
plot->host = plothost;//hostview标识符
s.Format(_T("%d"), i);
plot->identifier = s;//标识符
plot->barWidth = 4;// bar的宽度,按像素
plot->barWidthOffset = 2;//与下一个plot之间的间隔,按像素
plot->dataSource = this;//数据源代理
if (i == 0)
{
plot->legendTitle.Format(_T("销售金额"));//图例名称
ls.lineColor = RGB(115, 225, 65);//plot的颜色
}
else if (i == 1)
{
plot->legendTitle.Format(_T("退货金额"));//图例名称
ls.lineColor = RGB(245, 85, 70);//plot的颜色
}
plot->dataLineStyle = ls;
graph->addPlot(plot);//将plot添加到画布
legend->AddPlot(plot);//将该plot添加到图例
}
host->ShowLegend();//显示图例

如上图,里面有两个BarPlot,绿色的一个,红色的一个。

barWidth与barWidthOffset

barWidth:Bar的宽度
barWidthOffset:Bar与下一个Bar之间的间隔,如下图:

W1与W2是每个Bar的宽度,sep1为Bar1与Bar2的间隔距离,w为主刻度宽度,左右两侧的宽度x是根据w、W1、W2、sep1自动计算出来的。

数据源代理,实现CPTBarPlotDataSource接口

  • int numberOfRecordsForPlot(CPTPlot* plot)

    返回X轴主刻度数量
  • NSNumber numberForPlot(CPTPlot *plot, UINT fieldEnum, UINT recordIndex)

    根据X轴主刻度索引recordIndex返回对应的Y值
    NSNumber CDuiPanelRp24::numberForPlot(CPTPlot *plot, UINT fieldEnum, UINT recordIndex)
    {
    NSNumber ret;
    if (fieldEnum == CPTScatterPlotFieldX)
    {
    ret.idata = recordIndex;
    }
    else
    {
    IParameters* pi;
    CString netwr;
    CString month;
    month.Format(_T("%d"), recordIndex + 1);
    CString id = plot->identifier;
    CString host = plot->host;
    if (host == _T("bennian"))
    {
    switch (_ttoi(id))
    {
    case 0:
    pi=m_bennian.IParametersOfKey(month);
    pi->GetParameter(_T("xsje"), netwr);
    break;
    case 1:
    pi = m_bennian.IParametersOfKey(month);
    pi->GetParameter(_T("thje"), netwr);
    break;
    }
    }
    }
    }