【问题标题】:Cocoa Touch CorePlot scatter plot graph not showingCocoa Touch CorePlot 散点图未显示
【发布时间】:2012-01-10 15:37:44
【问题描述】:

我一直在使用 CorePlot 绘制饼图,之前效果很好。我现在想在我现有的饼图下方的散点图中可视化数据。为此,我使用 InterfaceBuilder 添加了一个新视图,与已经托管我的饼图的视图相同。我已将数据源和委托设置为 self,并且正确调用了相应的委托方法。看似唯一不起作用的是在托管视图中实际显示的图表。

这就是它的样子。顶部:工作饼图;底部:我的散点图应该是什么:

散点图唯一可见的是小矩形。

下面是对应的代码:

- (id)init
{
    // ...

    sp1 = [[MyPlotClass alloc] initWithTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];

    // the following returns an NSArray. Everything working as expected here.
    pieChartData = [self getEMDTurnoverSums];
    [pieChartData retain];

    sp2 = [[MyPlotClass alloc] initWithTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];

    // dito getEMDTurnoverSums
    scatterPlotData = [self getEMDTurnoverData];
    [scatterPlotData retain];

    return self;
}

- (void)viewDidLoad
{
    /*
     * ------------------------
     *      Pie Chart
     * ------------------------
     */

    graph1 = [sp1 getPieChartGraphForView:graphView1];

    CPTPieChart *pieChart = [sp1 initPieChartWithIdentifier:@"emd" andLineWidth:1.0f];
    pieChart.dataSource = self;
    pieChart.delegate   = self;

    CPTLegend *legend = [CPTLegend legendWithGraph:graph1];
    legend.numberOfColumns = 1;
    legend.numberOfRows    = 3;
    legend.cornerRadius    = 5.0;

    CPTMutableTextStyle *textStyle = [[[CPTMutableTextStyle alloc] init] autorelease];
    textStyle.fontSize             = 15.0;
    legend.textStyle               = textStyle;

    graph1.legend             = legend;
    graph1.legendAnchor       = CPTRectAnchorLeft;
    graph1.legendDisplacement = CGPointMake(30.0, 30.0);

    if (self.interfaceOrientation == UIDeviceOrientationLandscapeLeft ||
        self.interfaceOrientation == UIDeviceOrientationLandscapeRight)
    {
        graphView1.frame = CGRectMake(5.0f, 500.0f, 750.0f, 510.0f);
    }

    [graph1 addPlot:pieChart];
    [pieChart release];

    /*
     * ------------------------
     *      Scatter Plot
     * ------------------------
     */

    graph2 = [sp2 getScatterPlotGraphForView:graphView2];

    CPTScatterPlot *scatterPlot = [sp2 initScatterPlotWithIdentifier:@"scatterPlot" andLineWidth:5.0f andColor:[CPTColor blackColor]];
    scatterPlot.dataSource = self;
    scatterPlot.delegate   = self;

    CPTLegend *scatterPlotLegend = [CPTLegend legendWithGraph:graph2];
    scatterPlotLegend.numberOfColumns = 2;
    scatterPlotLegend.numberOfRows    = 3;
    scatterPlotLegend.cornerRadius    = 5.0;

    // see PieChart
    scatterPlotLegend.textStyle = textStyle;

    graph2.legend = scatterPlotLegend;
    graph2.legendAnchor = CPTRectAnchorLeft;
    graph2.legendDisplacement = CGPointMake(30.0, 30.0);

    if (self.interfaceOrientation == UIDeviceOrientationLandscapeLeft ||
        self.interfaceOrientation == UIDeviceOrientationLandscapeRight)
    {
        graphView2.frame = CGRectMake(5.0f, 240.0f, 750.0f, 270.0f);
    }

    [graph2 addPlot:scatterPlot];
    [scatterPlot release];

    /*
     * ------------------------
     *       END PLOTS
     * ------------------------
     */

    [super viewDidLoad];
}

委托方法:

- (NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    if ([(NSString *)plot.identifier isEqualToString:@"emd"]) {
        NSLog(@"numberOfRecordsForPlot: emd: %i", [pieChartData count]);

        return [pieChartData count];
    } else if ([(NSString *)plot.identifier isEqualToString:@"scatterPlot"]) {
        NSLog(@"numberOfRecordsForPlot: scatterPlot: %i", [scatterPlotData count]);
        NSLog(@"numberOfRecordsForPlot: scatterPlot: %@", scatterPlotData);

        return [scatterPlotData count];
    }

    return 0;
}

- (NSNumber *)numberForPlot:(CPTPlot *)plot
                      field:(NSUInteger)fieldEnum
                recordIndex:(NSUInteger)index
{
    if ([(NSString *)plot.identifier isEqualToString:@"emd"]) {
        return [pieChartData objectAtIndex:index];
    } else if ([(NSString *)plot.identifier isEqualToString:@"scatterPlot"]) {
        NSDictionary *fieldMapping = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:
                                                                          @"e_turnover",
                                                                          @"m_turnover",
                                                                          @"d_turnover",
                                                                          @"na_turnover",
                                                                          @"sum_turnover",
                                                                          nil]
                                                                 forKeys:[NSArray arrayWithObjects:
                                                                          @"0",
                                                                          @"1",
                                                                          @"2",
                                                                          @"3",
                                                                          @"4",
                                                                          nil]];

        NSLog(@"scatterPlotData: %@", scatterPlotData);
        NSLog(@"fieldMapping   : %@", fieldMapping);

        NSNumber *returnValue = [(NSDictionary *)[scatterPlotData objectAtIndex:index] objectForKey:
                                 [fieldMapping objectForKey:
                                  [NSString stringWithFormat:@"%i", fieldEnum]]];
        NSLog(@"returnValue: %@", returnValue);

        return returnValue;
    }

    return 0;
}

- (NSString *)legendTitleForPieChart:(CPTPieChart *)pieChart
                         recordIndex:(NSUInteger)index
{
    switch (index) {
        case 0:
            return [NSString stringWithFormat:@"Easy Lines - %@ €", [self standardFormatNumber:(NSNumber *)[pieChartData objectAtIndex:0] asDecimal:NO]];

        case 1:
            return [NSString stringWithFormat:@"Medium Lines - %@ €", [self standardFormatNumber:(NSNumber *)[pieChartData objectAtIndex:1] asDecimal:NO]];

        case 2:
            return [NSString stringWithFormat:@"Difficult Lines - %@ €", [self standardFormatNumber:(NSNumber *)[pieChartData objectAtIndex:2] asDecimal:NO]];

        default:
            break;
    }

    return @"";
}



- (CPTFill *)sliceFillForPieChart:(CPTPieChart *)pieChart
                      recordIndex:(NSUInteger)index
{
    switch (index) {
        case 0:
            return [CPTFill fillWithColor:[CPTColor greenColor]];

        case 1:
            return [CPTFill fillWithColor:[CPTColor yellowColor]];

        case 2:
            return [CPTFill fillWithColor:[CPTColor redColor]];

        default:
            break;
    }

    return [CPTFill fillWithColor:[CPTColor blackColor]];
}

这是来自 MyPlotClass.m 的代码:

#import "MyPlotClass.h"

@implementation MyPlotClass

@synthesize paddingLeft;
@synthesize paddingTop;
@synthesize paddingRight;
@synthesize paddingBottom;

@synthesize plotRangeXFrom;
@synthesize plotRangeXLength;
@synthesize plotRangeYFrom;
@synthesize plotRangeYLength;

@synthesize plotSpace;

@synthesize axisLineWidth;
@synthesize axisLineColor;

@synthesize minorTickLengthX;
@synthesize majorTickLengthX;
@synthesize minorTickLengthY;
@synthesize majorTickLengthY;
@synthesize majorIntervalLengthX;
@synthesize majorIntervalLengthY;
@synthesize labelOffsetX;
@synthesize labelOffsetY;
@synthesize minorTicksPerIntervalX;
@synthesize minorTicksPerIntervalY;

@synthesize pieChartRadius;
@synthesize pieChartStartAngle;
@synthesize pieChartSliceDirection;


- (id)init
{
    return [self initWithTheme:[CPTTheme themeNamed:kCPTPlainWhiteTheme]];
}

- (MyPlotClass *)initWithTheme:(CPTTheme *)theme
{
    graph = [[[CPTXYGraph alloc] initWithFrame:CGRectZero] retain];
    [graph applyTheme:theme];

    paddingLeft   = 20.0;
    paddingTop    = 20.0;
    paddingRight  = 20.0;
    paddingBottom = 20.0;

    plotRangeXFrom   = 0.0;
    plotRangeXLength = 0.0;
    plotRangeYFrom   = 0.0;
    plotRangeYLength = 0.0;

    axisLineWidth = 0.0f;
    axisLineColor = [CPTColor blackColor];

    minorTickLengthX       = 0.0f;
    majorTickLengthX       = 0.0f;
    minorTickLengthY       = 0.0f;
    majorTickLengthY       = 0.0f;
    majorIntervalLengthX   = 5.0f;
    majorIntervalLengthY   = 5.0f;
    labelOffsetX           = 3.0f;
    labelOffsetY           = 3.0f;
    minorTicksPerIntervalX = 0;
    minorTicksPerIntervalY = 0;

    pieChartRadius         = 100.0;
    pieChartStartAngle     = M_PI;
    pieChartSliceDirection = CPTPieDirectionClockwise;

    return self;
}


- (CPTXYGraph *)getScatterPlotGraphForView:(UIView *)view
{
    CPTGraphHostingView *hostingView = (CPTGraphHostingView *)view;
    hostingView.hostedGraph = graph;

    graph.paddingLeft   = paddingLeft;
    graph.paddingTop    = paddingTop;
    graph.paddingRight  = paddingRight;
    graph.paddingBottom = paddingBottom;

    plotSpace = (CPTXYPlotSpace *)graph.defaultPlotSpace;
    plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(plotRangeXFrom)
                                                    length:CPTDecimalFromFloat(plotRangeXLength)];
    plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(plotRangeYFrom)
                                                    length:CPTDecimalFromFloat(plotRangeYLength)];

    CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
    axisLineStyle.lineColor = axisLineColor;
    axisLineStyle.lineWidth = axisLineWidth;

    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;

    axisSet.xAxis.majorIntervalLength   = [[NSNumber numberWithFloat:majorIntervalLengthX] decimalValue];
    axisSet.xAxis.minorTicksPerInterval = minorTicksPerIntervalX;
    axisSet.xAxis.majorTickLineStyle    = axisLineStyle;
    axisSet.xAxis.minorTickLineStyle    = axisLineStyle;
    axisSet.xAxis.axisLineStyle         = axisLineStyle;
    axisSet.xAxis.minorTickLength       = minorTickLengthX;
    axisSet.xAxis.majorTickLength       = majorTickLengthX;
    axisSet.xAxis.labelOffset           = labelOffsetX;

    axisSet.yAxis.majorIntervalLength   = [[NSNumber numberWithInt:majorIntervalLengthY] decimalValue];
    axisSet.yAxis.minorTicksPerInterval = minorTicksPerIntervalY;
    axisSet.yAxis.majorTickLineStyle    = axisLineStyle;
    axisSet.yAxis.minorTickLineStyle    = axisLineStyle;
    axisSet.yAxis.axisLineStyle         = axisLineStyle;
    axisSet.yAxis.minorTickLength       = minorTickLengthY;
    axisSet.yAxis.majorTickLength       = majorTickLengthY;
    axisSet.yAxis.labelOffset           = labelOffsetY;

    return graph;
}

- (CPTXYGraph *)getPieChartGraphForView:(UIView *)view
{
    CPTGraphHostingView *hostingView = (CPTGraphHostingView *)view;
    hostingView.hostedGraph = graph;

    graph.paddingLeft   = paddingLeft;
    graph.paddingTop    = paddingTop;
    graph.paddingRight  = paddingRight;
    graph.paddingBottom = paddingBottom;

    CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
    axisLineStyle.lineColor = axisLineColor;
    axisLineStyle.lineWidth = axisLineWidth;

    CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;

    axisSet.xAxis.majorIntervalLength   = [[NSNumber numberWithFloat:majorIntervalLengthX] decimalValue];
    axisSet.xAxis.minorTicksPerInterval = minorTicksPerIntervalX;
    axisSet.xAxis.majorTickLineStyle    = axisLineStyle;
    axisSet.xAxis.minorTickLineStyle    = axisLineStyle;
    axisSet.xAxis.axisLineStyle         = axisLineStyle;
    axisSet.xAxis.minorTickLength       = minorTickLengthX;
    axisSet.xAxis.majorTickLength       = majorTickLengthX;
    axisSet.xAxis.labelOffset           = labelOffsetX;

    axisSet.yAxis.majorIntervalLength   = [[NSNumber numberWithInt:majorIntervalLengthY] decimalValue];
    axisSet.yAxis.minorTicksPerInterval = minorTicksPerIntervalY;
    axisSet.yAxis.majorTickLineStyle    = axisLineStyle;
    axisSet.yAxis.minorTickLineStyle    = axisLineStyle;
    axisSet.yAxis.axisLineStyle         = axisLineStyle;
    axisSet.yAxis.minorTickLength       = minorTickLengthY;
    axisSet.yAxis.majorTickLength       = majorTickLengthY;
    axisSet.yAxis.labelOffset           = labelOffsetY;

    return graph;
}


- (CPTScatterPlot *)initScatterPlotWithIdentifier:(NSString *)identifier
{
    return [self initScatterPlotWithIdentifier:identifier andLineWidth:3.0f andColor:[CPTColor blackColor]];
}

- (CPTScatterPlot *)initScatterPlotWithIdentifier:(NSString *)identifier
                                     andLineWidth:(CGFloat)lineWidth
                                         andColor:(CPTColor *)lineColor
{
    CPTScatterPlot *scatterPlot = [[[CPTScatterPlot alloc]
                                    initWithFrame:graph.defaultPlotSpace.accessibilityFrame]
                                   autorelease];

    scatterPlot.identifier = identifier;
    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.lineWidth = lineWidth;
    lineStyle.lineColor = lineColor;
    scatterPlot.dataLineStyle = lineStyle;
    [graph addPlot:scatterPlot];

    CPTPlotSymbol *greenCirclePlotSymbol = [CPTPlotSymbol ellipsePlotSymbol];
    greenCirclePlotSymbol.fill = [CPTFill fillWithColor:[CPTColor greenColor]];
    greenCirclePlotSymbol.size = CGSizeMake(2.0, 2.0);
    scatterPlot.plotSymbol     = greenCirclePlotSymbol;

    return scatterPlot;
}

- (CPTPieChart *)initPieChartWithIdentifier:(NSString *)identifier
                               andLineWidth:(CGFloat)lineWidth
{
    CPTPieChart *pieChart = [[[CPTPieChart alloc]
                              initWithFrame:graph.defaultPlotSpace.accessibilityFrame]
                             autorelease];

    pieChart.identifier     = identifier;
    pieChart.pieRadius      = pieChartRadius;
    pieChart.startAngle     = pieChartStartAngle;
    pieChart.sliceDirection = pieChartSliceDirection;

    // Prepare a radial overlay gradient for shading/gloss
    CPTGradient *overlayGradient = [[[CPTGradient alloc] init] autorelease];
    overlayGradient.gradientType = CPTGradientTypeRadial;
    overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.0] atPosition:0.0];
    overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.3] atPosition:0.9];
    overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.7] atPosition:1.0];
    pieChart.overlayFill = [CPTFill fillWithGradient:overlayGradient];

    CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
    lineStyle.lineWidth = lineWidth;
    pieChart.borderLineStyle = lineStyle;

    [graph addPlot:pieChart];

    return pieChart;
}


- (void)dealloc
{
    [super dealloc];

    [graph release];
    [plotSpace release];
}


@end

我已经为此花费了数小时,但仍未能确定问题所在。数据很好,委托方法被调用并返回正确的值。

TIA!

【问题讨论】:

    标签: objective-c ios xcode cocoa-touch core-plot


    【解决方案1】:

    一些观察:

    1. -initScatterPlotWithIdentifier:andLineWidth:andColor: 中,散点图添加到graph。不应该是graph2吗?

    2. -numberForPlot:field:recordIndex: 中,您必须检查字段参数——switch 语句运行良好。每个索引都会调用此方法两次,一次使用field == CPTScatterPlotFieldX,一次使用field == CPTScatterPlotFieldY。您为两个字段返回相同的值,因此即使您可以看到该图,它也将是一条对角线。

    3. axisLineWidth = 0.0f; 您需要为散点图增加此值,以便显示轴线。

    【讨论】:

      【解决方案2】:

      @Eric Skroch:

      感谢您的评论!

      1. 不,-initScatterPlotWithIdentifier:andLineWidth:andColor:MyPlotClass 中的一个方法。成员graph与实现类中的变量无关。

      2. 我实际上是在 return 语句中这样做的。然而,我认为我在这里牺牲了可读性以追求优雅。下面的代码现在更明显了:

        NSDictionary *curDict = (NSDictionary *)[scatterPlotData objectAtIndex:index];

        switch (fieldEnum) {

        case 0:
            return [curDict objectForKey:@"e_turnover"];
        
        case 1:
            return [curDict objectForKey:@"m_turnover"];
        
        case 2:
            return [curDict objectForKey:@"d_turnover"];
        
        case 3:
            return [curDict objectForKey:@"na_turnover"];
        
        case 4:
            return [curDict objectForKey:@"sum_turnover"];
        
        default:
            break;
        

        }

      顺便说一句:抱歉,我将此评论放在单独的答案中,但评论字段不允许我输入超过一定字符数的多行代码块或 cmets。

      【讨论】: