سؤال

بالنسبة لجزء من طلبي، أحتاج إلى إنشاء صورة لعرض معين وجميع طرق العرض الفرعية الخاصة به.

للقيام بذلك، أقوم بإنشاء سياق يغلف صورة نقطية بنفس حجم العرض، لكنني غير متأكد من كيفية رسم التسلسل الهرمي للعرض فيه.يمكنني رسم عرض واحد فقط عن طريق ضبط السياق واستدعاء drawRect بشكل صريح، لكن هذا لا يتعامل مع جميع طرق العرض الفرعية.

لا أستطيع رؤية أي شيء في واجهة NSView يمكن أن يساعد في هذا الأمر، لذا أظن أن الحل قد يكمن في مستوى أعلى.

هل كانت مفيدة؟

المحلول

لقد وجدت أن كتابة كود الرسم بنفسي كانت أفضل طريقة للقيام بما يلي:

  • التعامل مع مشكلات الشفافية المحتملة (بعض الخيارات الأخرى تضيف خلفية بيضاء إلى الصورة بأكملها)
  • كان الأداء أفضل بكثير

الكود أدناه ليس مثاليًا، لأنه لا يتعامل مع مشكلات القياس عند الانتقال من الحدود إلى الإطارات، ولكنه يأخذ في الاعتبار حالة isFlipped، ويعمل جيدًا لما استخدمته من أجله.لاحظ أنه يرسم فقط طرق العرض الفرعية (وطرق العرض الفرعية،...بشكل متكرر)، ولكن جعله يرسم نفسه أيضًا أمر سهل للغاية، فقط قم بإضافة [self drawRect:[self bounds]] في تنفيذ imageWithSubviews.

- (void)drawSubviews
{
    BOOL flipped = [self isFlipped];

    for ( NSView *subview in [self subviews] ) {

        // changes the coordinate system so that the local coordinates of the subview (bounds) become the coordinates of the superview (frame)
        // the transform assumes bounds and frame have the same size, and bounds origin is (0,0)
        // handling of 'isFlipped' also probably unreliable
        NSAffineTransform *transform = [NSAffineTransform transform];
        if ( flipped ) {
            [transform translateXBy:subview.frame.origin.x yBy:NSMaxY(subview.frame)];
            [transform scaleXBy:+1.0 yBy:-1.0];
        } else
            [transform translateXBy:subview.frame.origin.x yBy:subview.frame.origin.y];
        [transform concat];

        // recursively draw the subview and sub-subviews
        [subview drawRect:[subview bounds]];
        [subview drawSubviews];

        // reset the transform to get back a clean graphic contexts for the rest of the drawing
        [transform invert];
        [transform concat];
    }
}

- (NSImage *)imageWithSubviews
{
    NSImage *image = [[[NSImage alloc] initWithSize:[self bounds].size] autorelease];
    [image lockFocus];
    // it seems NSImage cannot use flipped coordinates the way NSView does (the method 'setFlipped:' does not seem to help)
    // Use instead an NSAffineTransform
    if ( [self isFlipped] ) {
        NSAffineTransform *transform = [NSAffineTransform transform];
        [transform translateXBy:0 yBy:NSMaxY(self.bounds)];
        [transform scaleXBy:+1.0 yBy:-1.0];
        [transform concat];
    }
    [self drawSubviews];
    [image unlockFocus];
    return image;
}

نصائح أخرى

يمكنك استخدام -[NSView dataWithPDFInsideRect:] لعرض التسلسل الهرمي الكامل للعرض الذي ترسله إليه في ملف PDF، ويتم إرجاعه كملف NSData هدف.يمكنك بعد ذلك أن تفعل ما يحلو لك مع ذلك، بما في ذلك تحويله إلى صورة نقطية.

هل أنت متأكد من أنك تريد تمثيل الصورة النقطية بالرغم من ذلك؟بعد كل شيء، يمكن أن يكون ملف PDF هذا (على الأقل من الناحية النظرية) مستقلاً عن الدقة.

يمكنك استخدام -[NSBitmapImageRep initWithFocusedViewRect:] بعد قفل التركيز على طريقة العرض لجعل العرض يعرض نفسه (وعروضه الفرعية) في المستطيل المحدد.

ما تريد القيام به متاح بشكل واضح بالفعل.راجع القسم "واجهة برمجة تطبيقات إعادة توجيه الرسم NSView" في ملاحظات إصدار AppKit 10.4.

أنشئ NSBitmapImageRep للتخزين المؤقت وقم بمسحه:

NSGraphicsContext *bitmapGraphicsContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:cacheBitmapImageRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:bitmapGraphicsContext];
[[NSColor clearColor] set];
NSRectFill(NSMakeRect(0, 0, [cacheBitmapImageRep size].width, [cacheBitmapImageRep size].height));
[NSGraphicsContext restoreGraphicsState];

ذاكرة التخزين المؤقت لذلك:

-[NSView cacheDisplayInRect:toBitmapImageRep:]

إذا كنت تريد الرسم بشكل عام في معالجة سياق محدد لعرض التكرار والشفافية بشكل صحيح،

-[NSView displayRectIgnoringOpacity:inContext:]

نعم، بالنسبة لهذا الاستخدام المحدد، فإن بيانات الصورة غير المقاسة هي بالضبط ما أحتاج إليه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top