#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 # с помощью делегирования.) Хорошее объяснение по управлению памятью!