【发布时间】:2016-08-05 10:45:03
【问题描述】:
因为你永远不知道,它可能有用,我一直在尝试编写一个灵活的 NSSplitView 实验应用程序,可以在其中以用户想要的任何方式动态添加和删除视图。那一点我能做到。
现在我认为能够:
交换视图 - 例如,在一个四视图窗口中,左上角的视图可以拖动到右下角,并且在释放鼠标按钮时,视图会相互交换。
拖出视图 - 例如,在一个四视图窗口中,如果左上角的视图被拖出它的包含窗口,那么它将成为一个包含该视图的窗口,并且原来的窗口将变成一个三视图窗口。
将视图拖入 - 以便将窗口拖入视图,关闭窗口并将其视图添加到它被拖入的窗口中。
我已经编写了一个程序来处理第一个问题(灵活设置拆分视图)https://github.com/HeadBanging/SplitViewTest,但我完全不知道如何去做剩下的事情——尤其是第一点。
如果您查看代码,您会发现我已经开始了(使用 Apple 和其他地方的教程),但它并没有达到我想要的效果。有人有什么建议吗?
当然,如果您只需要为您的项目提供一个灵活的拆分窗口,那么就可以了 - 有我的(在上面下载),没有使用限制 - 一切顺利。
Willeke 对如何使拖动工作有一些很好的建议,我已经实现如下(Git 上的完整代码):
#pragma mark Dragging
- (NSImage *)imageRepresentationOfView:(NSView*)draggingView {
BOOL wasHidden = draggingView.isHidden;
CGFloat wantedLayer = draggingView.wantsLayer;
draggingView.hidden = NO;
draggingView.wantsLayer = YES;
NSImage *image = [[NSImage alloc] initWithSize:draggingView.bounds.size];
[image lockFocus];
CGContextRef ctx = [NSGraphicsContext currentContext].graphicsPort;
[draggingView.layer renderInContext:ctx];
[image unlockFocus];
draggingView.wantsLayer = wantedLayer;
draggingView.hidden = wasHidden;
return image;
}
- (void)mouseDown:(NSEvent *)theEvent {
NSSize dragOffset = NSMakeSize(0.0, 0.0);
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
[pboard declareTypes:[NSArray arrayWithObject:NSTIFFPboardType] owner:self];
DebugView *hitView;
NSPoint startLocation = NSMakePoint(0, 0);
NSImage *draggedImage;
BOOL found = NO;
fHitView = nil;
while ((hitView = [[[self subviews] objectEnumerator] nextObject]) && !found) {
if ([hitView isKindOfClass:[DebugView class]] && [(DebugView *)hitView dragEnabled]) { //Change DebugView to Draggable View, and use as container for plugin views
draggedImage = [self imageRepresentationOfView:hitView];
startLocation = hitView.frame.origin;
found = YES;
}
}
if (draggedImage != nil) {
[pboard setData:[draggedImage TIFFRepresentation] forType:NSTIFFPboardType];
[self dragImage:draggedImage at:startLocation offset:dragOffset
event:theEvent pasteboard:pboard source:self slideBack:YES];
}
return;
}
- (void)setHighlighted:(BOOL)value {
isHighlighted = value;
[self setNeedsDisplay:YES];
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
NSPasteboard *pboard = [sender draggingPasteboard];
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
NSArray *paths = [pboard propertyListForType:NSFilenamesPboardType];
for (NSString *path in paths) {
NSError *error = nil;
NSString *utiType = [[NSWorkspace sharedWorkspace]
typeOfFile:path error:&error];
if (![[NSWorkspace sharedWorkspace]
type:utiType conformsToType:(id)kUTTypeFolder]) {
[self setHighlighted:NO];
return NSDragOperationNone;
}
}
}
[self setHighlighted:YES];
return NSDragOperationEvery;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender {
[self setHighlighted:NO];
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
[self setHighlighted:NO];
DebugView *hitView;
BOOL found = NO;
fHitView = nil;
while ((hitView = [[[self subviews] objectEnumerator] nextObject]) && !found) {
if ([hitView isKindOfClass:[DebugView class]] && [(DebugView *)hitView dragEnabled]) {
found = YES;
}
}
NSView* tempView = [sender draggingSource];
[[[sender draggingSource] superview] replaceSubview:[sender draggingSource] with:hitView];
[self replaceSubview:hitView with:tempView];
[self setNeedsDisplay:YES];
[[[sender draggingSource] superview] setNeedsDisplay:YES];
return YES;
}
- (BOOL)isHighlighted {
return isHighlighted;
}
drop 部分起作用 - 有时视图准备接受 drop ,有时它没有(任何人看到我做错了什么吗? - 它应该一直工作,除非当被拖放到的视图是源视图)。
拼图的最后一块对我来说仍然是个谜(接受掉落,并交换意见)。任何提示都会非常感激地接受。
【问题讨论】:
-
我建议阅读Drag and Drop Programming Topics。使用
dragImage:at:offset:event:pasteboard:source:slideBack:、NSDraggingSource和NSDraggingDestination。 -
…即使我想要做的是拖动整个 NSView、按钮、小部件和所有内容,而不仅仅是一个 NSImage?正如我所说,我一直在关注教程(您甚至可能已经识别出一些代码来自教程!)但它似乎不起作用!
-
拖动的图像是数据的表示,数据可以是任何东西:文本sn-p,文件,图像,表格行,url,...。
-
啊。谢谢 - 我现在有了工作拖放的第一道曙光。至少,拖动位有效 - 但下降位没有那么多。下一步去哪里有什么好的提示吗?我还修复了代码的 GitHub,使其不再是 zip。
-
drop bit 也可以,交换
performDragOperation中的视图。
标签: objective-c cocoa drag-and-drop