如果 Cocoa 应用程序正在跟踪 mouseEntered() 事件,则拖动事件未收到
Dragging Events Not Receiving If mouseEntered() Events Is Tracking by Cocoa App
正在开发 Cocoa 应用程序,该应用程序需要做两件事以防万一 - :
1) 鼠标进入或退出
2) 鼠标拖拽文件到应用
我有观点A,
视图 A 已注册以接收拖动事件,并且
具有用于接收鼠标进入和退出事件的跟踪区域,
问题是:
如果我将文件拖到视图 A;视图 A 接收 mouseEntered: 事件而不是 draggingEntered: 事件。
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
{
NSLog(@"draggingEntered called");
}
- (void)mouseEntered:(NSEvent *)theEvent
{
NSLog(@"mouseEntered called");
}
2018-02-05 14:08:58.273 XXX_APP [3420:119122] mouseEntered called
2018-02-05 14:08:58.273 XXX_APP [3420:119122] draggingEntered called
问题是每当我将文件拖到视图时;它进入 mouseEntered()
不要进入 mouseDragged()。
有什么解决方法吗?
提前致谢。
我可能错了,但我相信拖动操作取决于鼠标进入视图,因此如果您正在跟踪鼠标事件,mouseEntered:
方法将始终首先被调用。也就是说,您可以延迟对 mouseEntered:
事件执行某些操作,让视图有时间查看它是否跟随拖动操作,如果是,则取消 mouseEntered:
调用。这可以使用 performSelector:withObject:afterDelay:
(使用用户可能不会注意到的非常短暂的延迟)和 cancelPreviousPerformRequestsWithTarget:
来完成,如下所示:
- (void)updateTrackingAreas {
[super updateTrackingAreas];
for (NSTrackingArea *trackingArea in self.trackingAreas) {
[self removeTrackingArea:trackingArea];
}
[self addTrackingArea:[[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil]];
}
- (void)_mouseEntered:(NSEvent *)event {
NSLog(@"mouseEntered");
//do something...
}
- (void)mouseEntered:(NSEvent *)event {
//pause 0.05 seconds before acting on this event,
//giving the view time to see if a draggingEntered: event is triggered
[self performSelector:@selector(_mouseEntered:) withObject:event afterDelay:0.05];
}
- (void)mouseExited:(NSEvent *)event {
NSLog(@"mouseExited");
//do something...
}
//assumes you've registered for drag events (e.g., in init):
// [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
//cancel pending _mouseEntered: call:
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"draggingEntered");
NSPasteboard *pasteboard = [sender draggingPasteboard];
return (([pasteboard.types containsObject:NSFilenamesPboardType]) ? NSDragOperationLink : NSDragOperationNone);
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pasteboard = [sender draggingPasteboard];
if ([pasteboard.types containsObject:NSFilenamesPboardType]) {
for (NSString *filePath in [pasteboard propertyListForType:NSFilenamesPboardType]) {
NSLog(@"dropped file: %@", filePath);
}
}
return YES;
}
正在开发 Cocoa 应用程序,该应用程序需要做两件事以防万一 - :
1) 鼠标进入或退出
2) 鼠标拖拽文件到应用
我有观点A, 视图 A 已注册以接收拖动事件,并且 具有用于接收鼠标进入和退出事件的跟踪区域,
问题是: 如果我将文件拖到视图 A;视图 A 接收 mouseEntered: 事件而不是 draggingEntered: 事件。
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
{
NSLog(@"draggingEntered called");
}
- (void)mouseEntered:(NSEvent *)theEvent
{
NSLog(@"mouseEntered called");
}
2018-02-05 14:08:58.273 XXX_APP [3420:119122] mouseEntered called
2018-02-05 14:08:58.273 XXX_APP [3420:119122] draggingEntered called
问题是每当我将文件拖到视图时;它进入 mouseEntered() 不要进入 mouseDragged()。 有什么解决方法吗?
提前致谢。
我可能错了,但我相信拖动操作取决于鼠标进入视图,因此如果您正在跟踪鼠标事件,mouseEntered:
方法将始终首先被调用。也就是说,您可以延迟对 mouseEntered:
事件执行某些操作,让视图有时间查看它是否跟随拖动操作,如果是,则取消 mouseEntered:
调用。这可以使用 performSelector:withObject:afterDelay:
(使用用户可能不会注意到的非常短暂的延迟)和 cancelPreviousPerformRequestsWithTarget:
来完成,如下所示:
- (void)updateTrackingAreas {
[super updateTrackingAreas];
for (NSTrackingArea *trackingArea in self.trackingAreas) {
[self removeTrackingArea:trackingArea];
}
[self addTrackingArea:[[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil]];
}
- (void)_mouseEntered:(NSEvent *)event {
NSLog(@"mouseEntered");
//do something...
}
- (void)mouseEntered:(NSEvent *)event {
//pause 0.05 seconds before acting on this event,
//giving the view time to see if a draggingEntered: event is triggered
[self performSelector:@selector(_mouseEntered:) withObject:event afterDelay:0.05];
}
- (void)mouseExited:(NSEvent *)event {
NSLog(@"mouseExited");
//do something...
}
//assumes you've registered for drag events (e.g., in init):
// [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
//cancel pending _mouseEntered: call:
[NSObject cancelPreviousPerformRequestsWithTarget:self];
NSLog(@"draggingEntered");
NSPasteboard *pasteboard = [sender draggingPasteboard];
return (([pasteboard.types containsObject:NSFilenamesPboardType]) ? NSDragOperationLink : NSDragOperationNone);
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pasteboard = [sender draggingPasteboard];
if ([pasteboard.types containsObject:NSFilenamesPboardType]) {
for (NSString *filePath in [pasteboard propertyListForType:NSFilenamesPboardType]) {
NSLog(@"dropped file: %@", filePath);
}
}
return YES;
}