У меня есть приложение, в котором в одном окне есть NSImageView.Пользователь должен иметь возможность перетаскивать ЛЮБОЙ ФАЙЛ / ПАПКА (не только изображения) в представление изображений, поэтому я подклассифицировал класс NSImageView, чтобы добавить поддержку этих типов.
Причина, по которой я выбрал NSImageView вместонормальный вид - потому что я также хотел отобразить анимацию (скажем, стрелку, указывающую вниз и идущую вверх и вниз), когда пользователь наводит курсор мыши на файлы, готовые к сбросу.Мой вопрос заключается в следующем: каков наилучший способ (самый эффективный, самый быстрый, с наименьшим использованием процессора и т. Д.) Сделать это?
На самом деле, я уже сделал это, но что заставило меня задать этот вопрос:тот факт, что когда я устанавливаю изображения для изменения со скоростью ниже 0,02 сек, он начинает отставать.Вот как я это сделал:
В подклассе NSImageView:
- есть ивар: NSTimer * animTimer;
- переопределить awakeFromNib, вызвав [super awakeFromNib] изагрузка изображений в массив (около 45 изображений) с использованием NSImage
- всякий раз, когда пользователь входит с файлами, запускает animTimer с частотой = 0,025 (меньше и отстает) и селектором, который устанавливает следующее изображение в массиве (называется drawNextImage)
- всякий раз, когда пользователь завершает перетаскивание или завершает его, вызывает [animTimer invalidate], чтобы прекратить обновление изображений
Вот как я устанавливаю изображение в подклассе:
- (void)drawNextImage
{
currentImageIndex++; // ivar / kNumberDNDImages is a constant defined as 46
if (currentImageIndex >= kNumberDNDImages) { currentImageIndex = 0;}
[super setImage: [imagesArray objectAtIndex: currentImageIndex]]; // imagesArray is ivar
}
Итак, как бы я сделал это достаточно быстро?Я бы хотел, чтобы частота составляла около 0,01 с, но с задержкой менее 0,025, так что это то, что я сейчас установил.О, и мои изображения имеют правильный размер (+ или - один пиксель или что-то), и они находятся в формате .png (мне нужна прозрачность - jpegs, например, не будет делать это).
РЕДАКТИРОВАТЬ:
Я попытался следовать предложению NSResponder и обновил свой метод следующим образом:
- (void)drawNextImage
{
currentImageIndex++;
if (currentImageIndex >= kNumberDNDImages) { currentImageIndex = 0;}
NSRect smallImgRect;
smallImgRect.origin = NSMakePoint(kSmallImageWidth * currentImageIndex, [self.bigDNDImage size].height); // Up left corner - ??
smallImgRect.size = NSMakeSize(kSmallImageWidth, [self.bigDNDImage size].height);
// Bottom left corner - ??
NSPoint imgPoint = NSMakePoint(([self bounds].size.width - kSmallImageWidth) / 2, 0);
[bigDNDImage drawAtPoint: imgPoint fromRect: smallImgRect operation: NSCompositeCopy fraction: 1];
}
Я также переместил этот метод и другие методы перетаскивания из подкласса NSImageView вПодкласс NSView у меня уже был.Все точно так же, за исключением суперкласса и этого метода.Я также изменил некоторые константы.
В моем раннем тестировании этого я получил несколько сообщений об ошибках / предупреждениях, которые не останавливали выполнение, говоря о NSGraphicsContext или о чем-то подобном.Теперь они исчезли, но вы точно знаете.Я понятия не имею, почему они появились и что они значат.Если они когда-нибудь появятся снова, я буду беспокоиться о них, а не сейчас:)
РЕДАКТИРОВАТЬ 2:
Это то, что я делаю сейчас:
- (void)drawNextImage
{
currentImageIndex++;
if (currentImageIndex >= kNumberDNDImages) { currentImageIndex = 0;}
[self drawCurrentImage];
}
- (void)drawCurrentImage
{
NSRect smallImgRect;
smallImgRect.origin = NSMakePoint(kSmallImageWidth * currentImageIndex, 0); // Bottom left, for sure
smallImgRect.size = NSMakeSize(kSmallImageWidth, [self.bigDNDImage size].height);
// Bottom left as well
NSPoint imgPoint = NSMakePoint(([self bounds].size.width - kSmallImageWidth) / 2, 0);
[bigDNDImage drawAtPoint: imgPoint fromRect: smallImgRect operation: NSCompositeCopy fraction: 1];
}
Иподвох здесь в том, чтобы вызвать drawCurrentImage при вызове drawRect (видите, на самом деле это было проще решить, чем я думал).
Теперь я должен сказать, что я не пробовал это с составным изображением, потому что я не могНе могу найти хороший и быстрый способ объединить более 40 изображений так, как я хотел (одно рядом с другим).Но для тех, кто не заинтересован, я изменил это, чтобы сделать то же самое, что и мой подкласс NSImageView (чтение 40+ изображений из массива и их отображение), и я не обнаружил скачка скорости: NSView столь же отстает от 0,025, что и NSImageView.Также я обнаружил некоторые проблемы при использовании основной анимации (изображение рисуется в странных местах вместо того, где я говорю ей) и некоторые предупреждения, говорящие о NSGraphicsContext, который я вообще не знаю, как решить (я полностьюнуб, когда дело доходит до рисования и тому подобное с инструментами Objective-C).Поэтому в настоящее время я использую NSImageView, если я не найду способ объединить все эти изображения и попробовать его с NSView.