Cocoa NSTextField 拖拽删除需要子类...真的吗?

发布于 2024-10-11 05:07:25 字数 1161 浏览 5 评论 0原文

直到今天,我还没有机会使用 NSWindow 本身以外的任何东西作为 NSDraggingDestination。当使用一个窗口作为通用的拖动目标时,NSWindow 会将这些消息传递给它的委托,允许您处理拖放而无需子类化 NSWindow。

文档 说:

虽然 NSDraggingDestination 是 宣布为非正式协议, NSWindow 和 NSView 是你的子类 创建采用协议只需要 实现那些方法 相关的。 (NSWindow 和 NSView 课程提供私人 所有的实施 方法。)窗口对象或 其代表可以实施这些 方法;然而,该代表的 如果满足以下条件,则优先执行 两者都有实现 地点。

今天,我有一个带有两个 NSTextField 的窗口,我希望它们具有不同的放置行为,并且我不想允许在窗口的其他任何地方放置。按照我解释文档的方式,似乎我要么必须对 NSTextField 进行子类化,要么在窗口的委托上创建一些巨大的意大利面条条件放置处理程序,该处理程序会针对每个视图对draggingLocation进行命中检查,以便选择不同的放置区域行为每个领域。

在任何情况下,如果您拥有少量的放置目标视图,基于 NSWindow 委托的集中放置处理程序方法似乎都会很繁重。同样,无论情况如何,子类化方法似乎都很繁重,因为现在放置处理代码位于视图类中,因此一旦您接受放置,您就必须想出某种方法将放置的数据封送回模型。 绑定文档< /a> 警告您不要尝试通过以编程方式设置 UI 值来驱动绑定。所以现在你也陷入了困境。

所以我的问题是:“真的吗!?这些是唯一可用的选择吗?还是我在这里错过了一些简单的东西?”

谢谢。

Until today, I've never had occasion to use anything other than an NSWindow itself as an NSDraggingDestination. When using a window as a one-size-fits-all drag destination, the NSWindow will pass those messages on to its delegate, allowing you to handle drops without subclassing NSWindow.

The docs say:

Although NSDraggingDestination is
declared as an informal protocol, the
NSWindow and NSView subclasses you
create to adopt the protocol need only
implement those methods that are
pertinent. (The NSWindow and NSView
classes provide private
implementations for all of the
methods.) Either a window object or
its delegate may implement these
methods; however, the delegate’s
implementation takes precedence if
there are implementations in both
places.

Today, I had a window with two NSTextFields on it, and I wanted them to have different drop behaviors, and I did not want to allow drops anywhere else in the window. The way I interpret the docs, it seems that I either have to subclass NSTextField, or make some giant spaghetti-conditional drop handlers on the window's delegate that hit-checks the draggingLocation against each view in order to select the different drop-area behaviors for each field.

The centralized NSWindow-delegate-based drop handler approach seems like it would be onerous in any case where you had more than a small handful of drop destination views. Likewise, the subclassing approach seems onerous regardless of the case, because now the drop handling code lives in a view class, so once you accept the drop you've got to come up with some way to marshal the dropped data back to the model. The bindings docs warn you off of trying to drive bindings by setting the UI value programmatically. So now you're stuck working your way back around that too.

So my question is: "Really!? Are those the only readily available options? Or am I missing something straightforward here?"

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

匿名的好友 2024-10-18 05:07:25

经过更多研究后,似乎“是的,确实,您的两个选择是子类化 NSTextField 或使用 NSWindowDelegate 来处理 drop。”我将进一步声明,对于花园品种的情况,“我想在一个窗口中使用多个放置区域”,这两种方法中更好的方法是使用带有命中检查的 NSWindowDelegate 方法,因为您可以避免以下问题在视图端放置处理代码。我最终在我的窗口委托类上使用了这个 DraggingUpdated: 方法:

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
    NSPasteboard *pboard = [sender draggingPasteboard];
    NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];

    if ([pboard.types containsObject: NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy))
    {
        NSView* hitView = [sender.draggingDestinationWindow.contentView hitTest: sender.draggingLocation];
        if (hitView && (hitView == mSourceTextField || hitView == mDestTextField))
        {
            return NSDragOperationCopy;            
        }
    }

    return NSDragOperationNone;
}

显然,整个图片还有更多内容,但到目前为止,这种基于 hitTest: 的方法对我来说一直有效。我怀疑如果使用基于多 NSCell 的控件(如 NSTableView 或 NSOutlineView),这会稍微复杂一些,但毫不奇怪,它们有自己的拖动处理方法。

希望这对其他人有帮助。

After a bit more research it appears that "Yes, really, your two options are to either subclass NSTextField or use your NSWindowDelegate to handle drops." I'll go further and make the claim that the better way of the two, for garden variety cases of, "I want multiple drop zones in a single window" is to use the NSWindowDelegate method with hit checks, since you avoid the issue of having your drop-handling code on the view side. I ended up with this draggingUpdated: method on my window delegate class:

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
    NSPasteboard *pboard = [sender draggingPasteboard];
    NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];

    if ([pboard.types containsObject: NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy))
    {
        NSView* hitView = [sender.draggingDestinationWindow.contentView hitTest: sender.draggingLocation];
        if (hitView && (hitView == mSourceTextField || hitView == mDestTextField))
        {
            return NSDragOperationCopy;            
        }
    }

    return NSDragOperationNone;
}

Obviously there's more to the whole picture, but this hitTest:-based approach has worked for me so far. I suspect that this would be slightly more complex if one were working with a multi-NSCell based control like an NSTableView or NSOutlineView, but unsurprisingly, those have their own drag handling methods.

Hope this helps someone else.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文