Вопрос по objective-c, cocoa, keyboard, nswindow, keydown – keyDown не вызывается

6

У меня есть собственный NSView под названием SurfaceView. Это contentView NSWindow и он обрабатывает основные события, такие как щелчок мыши и рисование. Но то, что я делаю, не имеет значения, оно не обрабатывает функцию keyDown. Я уже переопределяю acceptsFirstResponder, но ничего не происходит.

Если это имеет значение, я запускаю приложение с помощью пользовательского цикла NSEvent, показанного ниже:

NSDictionary* info = [[NSBundle mainBundle] infoDictionary];
NSString* mainNibName = [info objectForKey:@"NSMainNibFile"];

NSApplication* app = [NSApplication sharedApplication];
NSNib* mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:[NSBundle mainBundle]];
[mainNib instantiateNibWithOwner:app topLevelObjects:nil];

[app finishLaunching];

while(true)
{   
    NSEvent* event = [app nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate date] inMode:NSDefaultRunLoopMode dequeue:YES];
    [app sendEvent:event];

    // Some code is execute here every frame to do some tasks...

    usleep(5000);
}

Вот код SurfaceView:

@interface SurfaceView : NSView
{
    Panel* panel;
}

@property (nonatomic) Panel* panel;

- (void)drawRect:(NSRect)dirtyRect;
- (BOOL)isFlipped;
- (void)mouseDown:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)keyDown:(NSEvent *)theEvent;
- (BOOL)acceptsFirstResponder;
- (BOOL)becomeFirstResponder;

@end

--

@implementation SurfaceView

@synthesize panel;

- (BOOL)acceptsFirstResponder
{
    return YES;
};

- (void)keyDown:(NSEvent *)theEvent
{
    // this function is never called
};

...

@end

Вот как я создаю представление:

NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(left, top, wide, tall) styleMask:NSBorderlessWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO];

...

[window makeKeyAndOrderFront:nil];

SurfaceView* mainView = [SurfaceView alloc];
[mainView initWithFrame:NSMakeRect(0, 0, wide, tall)];
mainView.panel = panel;
[window setContentView:mainView];
[window setInitialFirstResponder:mainView];
[window setNextResponder:mainView];
[window makeFirstResponder:mainView];
@ Верный Да. Иwindow.firstResponder это SurfaceView. user1467310
Просто короткое примечание: удалите все объявления методов в файле интерфейса, так как они уже объявлены в NSView. Не нужно объявлять их снова. TheAmateurProgrammer
А также, что с точками с запятой в конце каждого метода? TheAmateurProgrammer
Вы переопределены-becomeFirstResponder тоже? И после вызова makeFirstResponder, вы можетеNSLog(@"%@", window.firstResponder) перепроверить, действительно ли SurfaceView является первым ответчиком? Vervious
@theAmateurProgrammer Это плохая практика, которую я заработал на C ++. user1467310

Ваш Ответ

2   ответа
2

В дополнение к ответу: установите флажок IB дляNSWindow.

Title Bar должны быть проверены. Это похоже наNSBorderlessWindowMask

enter image description here

23

Я узнал, что мешалоkeyDown событие от того, чтобы быть названным. Это былоNSBorderlessWindowMask маска, она предотвращает превращение окна в главное и главное окно. Итак, я создал подклассNSWindow называетсяBorderlessWindow:

@interface BorderlessWindow : NSWindow
{
}

@end

@implementation BorderlessWindow

- (BOOL)canBecomeKeyWindow
{
    return YES;
}

- (BOOL)canBecomeMainWindow
{
    return YES;
}

@end
Холли с *! Ты спас мой день!
Хорошо, это сработало как ожидалось. Благодарю.
Большое спасибо за это. Вы сэкономили мне много времени. Для тех, кто использует swift с NSViewController, вы можете просто сделать расширение NSWindow и вернуть true для этих методов.
@Epic Byte - это не правильно. Согласноdocumentation : & quot; Вы не можете использовать расширения для переопределения существующих методов или свойств для типов Objective C & quot;
Тогда это стоит исправить. Я потратил немного времени на то, чтобы это не сработало, прежде чем усомниться в комментариях и проверить документы.

Похожие вопросы