在 OSX 10.8 SDK/objective-c 中拖动按钮

2024-01-09

我开始使用 Objective-Ctoday为了开发 OSX(山狮)的应用程序。 我有一堆按钮,我想将它们拖到其他对象中,例如文本字段。我按照苹果开发网站上的教程进行操作,但我无法让拖动部分工作(放置部分工作,例如,我可以将文件从查找器拖到文本文件中并显示其路径)。

我首先创建一个 NSButton 子类:@interface mp3OCDDraggableButton : NSButton

并实施了如下所述的方法:https://developer.apple.com/library/mac/#samplecode/Cocoa DragAndDrop/Introduction/Intro.html https://developer.apple.com/library/mac/#samplecode/CocoaDragAndDrop/Introduction/Intro.html

但那东西不动!

我在 mouseDown: 中放置了一些日志消息,我可以在其中看到,但如果我将其替换为 mouseDragged: - 这会告诉我什么吗?

任何人都可以发布一个具有此功能的简单示例吗?我找不到任何有效的东西:\

提前谢谢了!

这是迄今为止我为可拖动按钮编写的代码。与教程中的几乎相同。

//myDraggableButton.h

@interface myDraggableButton : NSButton <NSDraggingSource, NSPasteboardItemDataProvider>
@end

and

//myDraggableButton.m

#import "myDraggableButton.h"

@implementation myDraggableButton

- (void)mouseDown:(NSEvent *)theEvent:(NSEvent*)event
{

    NSLog(@"mouseDown");

    NSPasteboardItem *pbItem = [NSPasteboardItem new];
    [pbItem setDataProvider:self forTypes:[NSArray arrayWithObjects:NSPasteboardTypeString, nil]];
    NSDraggingItem *dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:pbItem];
    NSRect draggingRect = self.bounds;
    [dragItem setDraggingFrame:draggingRect contents:[self image]];
    NSDraggingSession *draggingSession = [self beginDraggingSessionWithItems:[NSArray arrayWithObject:dragItem] event:event source:self];
    draggingSession.animatesToStartingPositionsOnCancelOrFail = YES;
    draggingSession.draggingFormation = NSDraggingFormationNone;
}

- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
    switch (context) {
        case NSDraggingContextOutsideApplication:
            return NSDragOperationCopy;
        case NSDraggingContextWithinApplication:
        default:
            return NSDragOperationCopy;
            break;
    }
}

- (BOOL)acceptsFirstMouse:(NSEvent *)event
{
    return YES;
}

- (void)pasteboard:(NSPasteboard *)sender item:(NSPasteboardItem *)item provideDataForType:(NSString *)type
{
    if ( [type compare: NSPasteboardTypeTIFF] == NSOrderedSame ) {
        [sender setData:[[self image] TIFFRepresentation] forType:NSPasteboardTypeTIFF];
    } else if ( [type compare: NSPasteboardTypePDF] == NSOrderedSame ) {
        [sender setData:[self dataWithPDFInsideRect:[self bounds]] forType:NSPasteboardTypePDF];
    }

}

@end

我为死灵术道歉,但我在尝试自己实现这个问题时偶然发现了这个问题,并想分享答案,因为它可能对其他人有用。

该解决方案使用类别NSActionCell and NSControl因为我需要能够拖动多种控件类型,而不仅仅是按钮。您可以根据您的需求/课程进行调整。

我已经注释掉了与隐藏/取消隐藏控件时出现不需要的淡入淡出动画的解决方法有关的代码。我摆弄了隐式动画等,但找不到更好的方法。这个黑客确实工作得很好,但我遗漏了窗口实现代码。

@implementation NSControl (DragControl)

- (NSDraggingSession*)beginDraggingSessionWithDraggingCell:(NSActionCell <NSDraggingSource> *)cell event:(NSEvent*) theEvent
{
    NSImage* image = [self imageForCell:cell];
    NSDraggingItem* di = [[NSDraggingItem alloc] initWithPasteboardWriter:image];
    NSRect dragFrame = [self frameForCell:cell];
    dragFrame.size = image.size;
    [di setDraggingFrame:dragFrame contents:image];

    NSArray* items = [NSArray arrayWithObject:di];

    [self setHidden:YES];
    return [self beginDraggingSessionWithItems:items event:theEvent source:cell];
}

- (NSRect)frameForCell:(NSCell*)cell
{
    // override in multi-cell cubclasses!
    return self.bounds;
}

- (NSImage*)imageForCell:(NSCell*)cell
{
    return [self imageForCell:cell highlighted:[cell isHighlighted]];
}

- (NSImage*)imageForCell:(NSCell*)cell highlighted:(BOOL) highlight
{
    // override in multicell cubclasses to just get an image of the dragged cell.
    // for any single cell control we can just make sure that cell is the controls cell

    if (cell == self.cell || cell == nil) { // nil signifies entire control
                                            // basically a bitmap of the control
                                            // NOTE: the cell is irrelevant when dealing with a single cell control
        BOOL isHighlighted = [cell isHighlighted];
        [cell setHighlighted:highlight];

        NSRect cellFrame = [self frameForCell:cell];

        // We COULD just draw the cell, to an NSImage, but button cells draw their content
        // in a special way that would complicate that implementation (ex text alignment).
        // subclasses that have multiple cells may wish to override this to only draw the cell
        NSBitmapImageRep* rep = [self bitmapImageRepForCachingDisplayInRect:cellFrame];
        NSImage* image = [[NSImage alloc] initWithSize:rep.size];

        [self cacheDisplayInRect:cellFrame toBitmapImageRep:rep];
        [image addRepresentation:rep];
        // reset the original cell state
        [cell setHighlighted:isHighlighted];
        return image;
    }
    // cell doesnt belong to this control!
    return nil;
}

#pragma mark NSDraggingDestination
// message forwarding doesnt work for NSDraggingDestination methods
// because NSView implements empty methods for the protocol
/*
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
{
    return [self.cell draggingEntered:sender];
}

- (void)draggingExited:(id < NSDraggingInfo >)sender
{
    [self.cell draggingExited:sender];
}

- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
{
    return [self.cell prepareForDragOperation:sender];
}

- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
{
    return [self.cell performDragOperation:sender];
}

- (void)concludeDragOperation:(id < NSDraggingInfo >)sender
{
    return [self.cell concludeDragOperation:sender];
}
*/
- (void)draggingEnded:(id < NSDraggingInfo >)sender
{
    // implement whatever you want to do here.
    [self setHidden:NO];
}

@end


static NSPoint _dragImageOffset;
@implementation NSActionCell (DragCell)

- (void)setControlView:(NSView *)view
{
    // this is a bit of a hack, but the easiest way to make the control dragging work.
    // force the control to accept image drags.
    // the control will forward us the drag destination events via our DragControl category

    [view registerForDraggedTypes:[NSImage imagePasteboardTypes]];
    [super setControlView:view];
}

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp
{
    BOOL result = NO;
    NSPoint currentPoint = theEvent.locationInWindow;
    BOOL done = NO;
    BOOL trackContinously = [self startTrackingAt:currentPoint inView:controlView];

    BOOL mouseIsUp = NO;
    NSEvent *event = nil;
    while (!done)
    {
        NSPoint lastPoint = currentPoint;

        event = [NSApp nextEventMatchingMask:(NSLeftMouseUpMask|NSLeftMouseDraggedMask)
                                   untilDate:[NSDate distantFuture]
                                      inMode:NSEventTrackingRunLoopMode
                                     dequeue:YES];

        if (event)
        {
            currentPoint = event.locationInWindow;

            // Send continueTracking.../stopTracking...
            if (trackContinously)
            {
                if (![self continueTracking:lastPoint
                                         at:currentPoint
                                     inView:controlView])
                {
                    done = YES;
                    [self stopTracking:lastPoint
                                    at:currentPoint
                                inView:controlView
                             mouseIsUp:mouseIsUp];
                }
                if (self.isContinuous)
                {
                    [NSApp sendAction:self.action
                                   to:self.target
                                 from:controlView];
                }
            }

            mouseIsUp = (event.type == NSLeftMouseUp);
            done = done || mouseIsUp;

            if (untilMouseUp)
            {
                result = mouseIsUp;
            } else {
                // Check if the mouse left our cell rect
                result = NSPointInRect([controlView
                                        convertPoint:currentPoint
                                        fromView:nil], cellFrame);
                if (!result)
                    done = YES;
            }

            if (done && result && ![self isContinuous])
                [NSApp sendAction:self.action
                               to:self.target
                             from:controlView];
            else {
                done = YES;
                result = YES;

                // this initiates the control drag event using NSDragging protocols
                NSControl* cv = (NSControl*)self.controlView;
                NSDraggingSession* session = [cv beginDraggingSessionWithDraggingCell:self
                                                                                event:theEvent];
                // _dragImageOffset = [cv convertPoint:[theEvent locationInWindow] fromView:nil];
                // Note that you will get an ugly flash effect when the image returns if this is set to yes
                // you can work around it by setting NO and faking the release by animating an NSWindowSubclass with the image as the content
                // create the window in the drag ended method for NSDragOperationNone
                // there is [probably a better and easier way around this behavior by playing with view animation properties.
                session.animatesToStartingPositionsOnCancelOrFail = YES;
            }

        }
    }
    return result;
}

#pragma mark - NSDraggingSource Methods
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
    switch(context) {
        case NSDraggingContextOutsideApplication:
            return NSDragOperationNone;
            break;

        case NSDraggingContextWithinApplication:
        default:
            return NSDragOperationPrivate;
            break;
    }
}
/*
- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint
{
    DragAnimationWindow* dw = [DragAnimationWindow sharedAnimationWindow];
    NSControl* cv = (NSControl*)self.controlView;

    NSImage* image = [[NSImage alloc] initWithPasteboard:session.draggingPasteboard];
    [dw setupDragAnimationWith:cv usingDragImage:image];
    [image release];
    NSRect frame = [cv frameForCell:self];
    frame = [cv convertRect:frame toView:nil];
    [dw setFrame:[cv.window convertRectToScreen:frame] display:NO];
}
*/
- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
{
    /*
    if (operation == NSDragOperationNone) {
        DragAnimationWindow* dw = [DragAnimationWindow sharedAnimationWindow];
        NSRect frame = dw.frame;

        NSPoint start = screenPoint;
        start.y += _dragImageOffset.y;
        start.x -= _dragImageOffset.x;

        [dw setFrameTopLeftPoint:start];
        [dw animateToFrame:frame];
    }*/
    // now tell the control view the drag ended so it can do any cleanup it needs
    // this is somewhat hackish
    [self.controlView draggingEnded:nil];
}

@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 OSX 10.8 SDK/objective-c 中拖动按钮 的相关文章

  • 高效创建 x 层深度的嵌套 for 循环

    这可能是一件简单的事情 但我需要创建一个循环结构 使其循环 y x 次以创建 x 和 y 的所有可能组合 例如 如果有 4 个 x 每个 x 有 2 个 y 我想做这样的事情 for int a 0 a lt y a for int b 0
  • 将 UIButton 中的图像缩放到 AspectFit?

    我想将图像添加到 UIButton 并且还想缩放图像以适合 UIButton 使图像变小 请告诉我该怎么做 这是我尝试过的 但它不起作用 将图像添加到按钮并使用setContentMode self itemImageButton setI
  • DatePicker 停止 CoreData 按预期工作

    我有一个应用程序 它保存 UIDatePicker 中的文本和日期 然后在您回到 UIDatePicker 中的该日期时显示该注释 效果很好 只有我发现将 UIDatePicker 日期设置为今天会停止 CoreData 工作 只有当我运行
  • 错误域=AVFoundationErrorDomain代码=-11814“无法记录”

    它不断给我错误 错误域 AVFoundationErrorDomain代码 11814 无法记录 我不确定问题是什么 我试图在拍照后计数器达到 1 时录制声音 static int counter counter will always b
  • 确定 Objective-C 方法在运行时是否是可变的

    有没有办法在运行时找出给定方法是否是可变参数类型 就像是method getTypeEncoding 这不会告诉我一个方法是否接受可变数量的参数 或者有什么技巧可以告诉我们吗 罗伯特的评论是正确的 考虑 interface Boogity
  • 频繁绘制 CGPath 时的性能

    我正在开发一个将数据可视化为折线图的 iOS 应用程序 该图被绘制为CGPath在全屏自定义中UIView最多包含 320 个数据点 数据经常更新 图表需要相应地重新绘制 刷新率为 10 秒就很好了 到目前为止很容易 然而 我的方法似乎需要
  • iphone:如何停止快门动画?

    我有两个问题 1 我想知道如何在相机加载时停止快门动画 我正在使用 UIImagePickerController 我已经参考了堆栈溢出的许多答案 但没有成功 2 我在相机中有一个自定义按钮 使用cameraOverlayView并想通过单
  • iPhone 和加密库

    我想我必须在我的 iPhone 应用程序中使用加密库 我想问你有关苹果公司实施的加密货币出口政策的影响 我需要做一些额外的事情吗 例如填写表格等 1 如果我使用 MD5 进行哈希处理 2 如果我使用对称加密 Thanks EDIT 2009
  • 我如何获取用户的电子邮件? iPhone SDK

    我需要获取 Mail app 中使用的用户的电子邮件地址 如何使用 iPhone SDK 做到这一点 谢谢你 简短的回答 你不能 如果需要 您应该提示用户输入电子邮件地址
  • Swift 闭包作为 AnyObject

    我尝试使用这个方法 class addMethod 在 Obj c 中使用如下 class addMethod self class selector eventHandler imp implementationWithBlock han
  • 如何在 ios 7 上更改重新排序控制图像

    我正在寻找一种更改重新排序控件图像和大小的方法 我使用此代码来更改重新排序图像 void tableView UITableView tableView willDisplayCell UITableViewCell cell forRow
  • iCloud loadFrom Contents - 如何处理 UIDocumentStateSavingError 和 UIDocumentStateEditingDisabled

    我在我的应用程序中使用 iCloud 来加载文本文件 加载文本文件时 当我调用时 iCloud 会调用此方法 UIDocument openWithCompletionHandler BOOL success etc BOOL loadFr
  • 带有 Core Data 对象的动态 UITableView 高度

    过去几天我一直在试图解决一个谜团 即为什么我的批处理大小为 20 的 NSFetchedResultsController 总是在获取完成后立即错误 即加载到内存中 我的所有对象 从而导致请求需要约 20 秒 事实证明 这是因为在我的 he
  • 是什么导致了这个 iPhone 崩溃日志?

    我有点卡住了 需要解决这个问题 因为我的一个应用程序出现了随机崩溃 而这些崩溃并不总是能够重现 这是崩溃日志之一 Incident Identifier 59865612 9F00 44EA 9474 2BF607AD662E CrashR
  • UISplitViewController - 推送模态视图

    使用 UISplitViewController 时推送模态视图的最佳实践是什么 您会从 RootViewController DetailViewController 还是直接从应用程序委托推送 理想情况下 我想要实现的功能是在基于某些条
  • 适用于 Objective-C / iPhone 的良好 HTTP 库? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 UPDATE 这个问题显然已经过时了 参见日期 我建议只使用现代 iOS7 功能 例如 NSURLSession 我想 这个问题是为了历史
  • UICollectionView 未出现

    我正在尝试设置UICollectionView 以编程方式在我的视图控制器中扩展UIViewController 由于某种原因 我的收藏视图根本没有显示 以下是我所拥有的 为什么没有出现 我将它连接到委托和数据源并将其添加为子视图self
  • 确定 NSView 是否绘制的正确方法

    有没有正确的方法来确定是否NSView实际上是否在当前视图层次结构中绘制 考虑以下情况 视图完全在屏幕外 不是强制性的 该视图不在视图层次结构的顶部 The isHidden and isHiddenOrHasHiddenAncestor不
  • 使用 Cocoa 获取无法安装的驱动器列表

    我想获取在 OS X 下使用 Cocoa Objective C 无法安装 弹出的驱动器列表 我希望 NSWorkspace getFileSystemInfoForPath 能帮助我 NSArray listOfMedia NSWorks
  • 避免“在此块中强烈捕获自身可能会导致保留周期”消息

    每次我必须在块内使用全局变量或属性时 如下所示 self save if isItSaving NO self saveMyFile 我必须像这样重写 BOOL iis isItSaving id myself self self save

随机推荐

  • Django 1.8 使用gmail SMTP发送邮件

    我正在尝试使用发送邮件smtp gmail com在 Django 1 8 中 My settings py包含 EMAIL BACKEND django smtp ssl SSLEmailBackend EMAIL HOST smtp g
  • 将C++类代码分成多个文件,有什么规则?

    思考时间 为什么你要分割你的文件 正如标题所示 我遇到的最终问题是多重定义链接器错误 我实际上已经解决了问题 但我没有以正确的方式解决问题 在开始之前 我想讨论一下将一个类文件拆分为多个文件的原因 我已经尝试将所有可能的情况都放在这里 如果
  • 以编程方式选择 UITextField 中的所有文本

    如何以编程方式选择 UITextField 中的所有文本 这就是我的窍门 self titleField setSelectedTextRange self titleField textRangeFromPosition self tit
  • 从 GridFS 中清除孤立文件

    我有一个引用 GridFS 文件的集合 通常每条记录 1 2 个文件 这些集合相当大 父集合中大约有 705k 条记录 以及 790k GridFS 文件 随着时间的推移 出现了许多孤立的 GridFS 文件 父记录已被删除 但引用的文件并
  • 防止 XSS 但仍允许 PHP 中使用某些 HTML

    我想阻止 XSS 攻击 但我仍然想允许 HTML 标签 例如 b u i img a 和 YouTube 视频播放器 我不想接受 XSS 攻击 我正在使用 PHP 我建议使用html净化器 http htmlpurifier org 它是最
  • 找不到 Microsoft.VisualBasic.Powerpacks.ShapeContainer

    我正在用 C 开发一个游戏 它在我的笔记本电脑上运行正常 但是当我尝试在其他电脑上运行它时 它出现错误 找不到 Microsoft VisualBasic Powerpacks ShapeContainer 我使用 Visual Studi
  • Vue 元素不通过 v-show 隐藏

    我假设 v show 将根据传递的数据显示 隐藏元素 由于某种原因 当 v show 为 false 时 我的元素不会动态隐藏 当我手动将变量 showNav 更改为 false 时 它 将在页面加载时隐藏 因此它似乎可以正常运行 我的变量
  • 无法在 Wear OS Samsung Galaxy Watch 4 上请求蓝牙权限

    我创建了一个示例 Wear OS 应用程序 它应该发现 BLE 设备 但我的代码需要蓝牙权限 当我将这些行放入清单中时
  • 角度 2 中的条件图像 Src 绑定

    三元条件如何写 img src在角度 2 中 下面是我尝试过的代码 但这不起作用 img class lib img height 500 width 500 alt default image src item pictureUrl nu
  • Nsdateformatter 以所选手机的语言返回日期。它可以一直只返回英文吗?

    我正在使用 dateformatter 来获取应用程序中的日期和时间 但是 当我更改手机日期格式器的语言时 我遇到了一个问题 它返回了手机所选语言的日期和时间 由于我们不支持多种语言 因此我的应用程序崩溃了 请找到下面的代码片段 NSDat
  • Android LocationManager 网络提供商返回 null

    我想使用 Android 应用程序获取我的 GPS 坐标 我开始开发 我可以获取GPS坐标 但它们不准确 我想使用 NETWORK PROVIDER 但该提供程序的位置始终为空 更有趣的是 isProvicerEnabled 返回 true
  • 通过 url 参数根据区域设置在 nginx 上设置自定义 404 错误页面

    我正在运行最新的稳定版本Nginx on GNU Linux操作系统并拥有以下虚拟主机 我正在尝试setup custom localized 404 error pages avoiding if但我总是陷入重定向循环 到目前为止 我只考
  • 对齐 html 电子邮件中表格中的数据单元格元素

    我有一个如下所示的屏幕截图 我必须在 HTML CSS 中复制它 附件是fiddle https jsfiddle net dehg79qs embedded result我现在可以复制它 我正在编写 HTML 电子邮件代码 因此这就是我在
  • 等待 asyncio.Future 会引发并发.futures._base.CancelledError,而不是等待设置值/异常

    当我运行以下 python 代码时 import asyncio import logging logging basicConfig level logging DEBUG async def read future fut print
  • 使用bundle exec运行rails控制台

    当我执行时bundle exec rails c我得到一个带有以下提示的 ruby 控制台 Loading development environment Rails 3 0 3 jruby 1 6 3 001 gt 一切看起来都按顺序进行
  • 将 console.log 转换为输出到 div

    我正在使用本主题中的简单 rss feed 解析器示例 Rss 解析器示例 https stackoverflow com questions 10943544 how to parse an rss feed using javascri
  • 应用程序关闭时发送通知

    当应用程序完全关闭时 如何以编程方式发送通知 示例 用户关闭了应用程序 也在 Android 任务管理器中 然后等待 应用程序应在 X 秒后或当应用程序检查更新时发送通知 我尝试使用这些代码示例 但是 应用程序关闭时推送通知 https s
  • sbt-assemble:跳过特定测试

    我想配置sbt assembly跳过特定的测试课程 有什么办法可以做到这一点吗 如果有帮助 我使用 ScalaTest 标记了测试 Network tag See 具有共享源的附加测试配置 http www scala sbt org 0
  • 0 在socket()系统调用中表示什么?

    下一行中的 0 表示什么 我还可以使用哪些其他标志 server socket AF UNIX SOCK STREAM 0 正如其他人可能所说的那样 第三个论点socket一般是一个int指示协议 0表示调用者不想指定协议并将其留给服务提供
  • 在 OSX 10.8 SDK/objective-c 中拖动按钮

    我开始使用 Objective Ctoday为了开发 OSX 山狮 的应用程序 我有一堆按钮 我想将它们拖到其他对象中 例如文本字段 我按照苹果开发网站上的教程进行操作 但我无法让拖动部分工作 放置部分工作 例如 我可以将文件从查找器拖到文