Добавление NSImageView во время выполнения не реагирует на событие наведения курсора мыши

#objective-c #cocoa

#objective-c #cocoa

Вопрос:

Я создал кнопку и элементы управления NSImageView во время выполнения. Кнопка отреагировала на событие click. Но imageview этого не делает. Есть предложения?

     NSView *superview = [((MyAppAppDelegate *)[NSApp delegate]).window contentView];

    NSButton *button = [ [ NSButton alloc ] initWithFrame: NSMakeRect(300, 50, 50.0, 50.0 ) ];
    [superview addSubview:button];
    [button setTarget:self];
    [button setAction:@selector(button_Clicked:)];

    NSImageView *myImageView = [[NSImageView alloc] initWithFrame:NSMakeRect(5, 5, 240, 240)];
    NSString* filePath = @"/Volumes/MAC DAT2/pictures/TVX1/153/MP6107frame5786.jpg";
    NSImage* image1 = [[NSImage alloc] initWithContentsOfFile:filePath];
    [myImageView setImage:image1];
    [superview addSubview:myImageView];
    [myImageView setTarget:self];
    [myImageView setAction:@selector(mouseDown:)];

}
- (IBAction)button_Clicked:(id)sender
{
    NSLog(@"button clicked");
}
-(void) mouseDown:(NSEvent *)event
//- (IBAction)mouseDown:(NSEvent *)event  //also have tried this one.
{
    NSLog(@"mousedown");

}
  

Редактировать: мне нужно использовать NSImageView , поэтому использование NSButton с изображением не является решением.

Комментарии:

1. Подкласс NSObject. Однако, смотрите Мой комментарий для NSGod, чтобы прояснить мой вопрос.

Ответ №1:

Прежде всего, в вашем коде есть несколько проблем с памятью: когда вы создаете локальные объекты с помощью alloc/init , а затем передаете эти объекты другим объектам, которые их сохранят, вам нужно либо -release , либо -autorelease объекты позже.

 NSView *superview = [((MyAppAppDelegate *)[NSApp delegate]).window contentView];

// memory leak averted:
NSButton *button = [[[NSButton alloc] initWithFrame:
                      NSMakeRect(300, 50, 50.0, 50.0 )] autorelease];

[superview addSubview:button];
[button setTarget:self];
[button setAction:@selector(button_Clicked:)];

// memory leak averted:
NSImageView *myImageView = [[[NSImageView alloc] initWithFrame:
                              NSMakeRect(5, 5, 240, 240)] autorelease];

NSString* filePath = @"/Volumes/MAC DAT2/pictures/TVX1/153/MP6107frame5786.jpg";

// memory leak averted:
NSImage* image1 = [[[NSImage alloc] initWithContentsOfFile:filePath] autorelease];

[myImageView setImage:image1];
[superview addSubview:myImageView];
[myImageView setTarget:self];
[myImageView setAction:@selector(mouseDown:)];
  

NSView ‘s -addSubview: вставляет представление в иерархию представлений, которая похожа на массив вложенных представлений. В результате -addSubview: сохраняется переданное вами представление, поэтому вам нужно автоматически выпустить его, чтобы противодействовать использованию вашего создания alloc . Когда вы вызываете NSImageView ‘s setImage: , оно сохраняет (или копирует) переданное вами изображение, поэтому вам также необходимо выполнить автоматический выпуск, чтобы противодействовать созданию с использованием alloc .

По умолчанию NSImageView не реагирует на -mouseDown: или -mouseUp: как это делают другие NSControl подклассы (а именно NSButton ). Если это работает визуально, возможно, имеет смысл настроить NSButton таким образом, чтобы просто показывать изображение, а не использовать NSImageView , в противном случае вам, вероятно, потребуется создать пользовательский подкласс NSImageView .

В NSImageView подклассе я бы серьезно подумал, правильно ли переопределять mouseDown: , или вам следует подождать, пока вы не получите mouseUp: , чтобы отправить свое действие. Например, большинство кнопок не отправляют свое действие сразу после нажатия мыши вниз; скорее, они ждут, пока вы отпустите мышь ( mouseUp: ), на случай, если пользователь захочет передумать.

В любом случае подкласс будет выглядеть следующим образом:

 @interface MDImageView : NSImageView {

}

@end

@implementation MDImageView

- (void)mouseUp:(NSEvent *)event {
      if ([[self target] respondsToSelector:[self action]]) {
         [NSApp sendAction:[self action] to:[self target] from:self];
      }
}

@end
  

Комментарии:

1. Вы были правы в отношении необходимого подкласса NSImageView. Имея это в виду, как вы реализуете событие mouseUp в вызывающем модуле (классе) — не из MDImageView? В принципе, мне нужно, чтобы мои методы обработчика событий мыши находились внутри вызывающего класса. (Вы можете сделать то же самое в C или C # с помощью делегирования.) Хорошее объяснение по управлению памятью!