在 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 中拖动按钮 的相关文章

  • Objective-C:在哪里定义宏以便随处可用?

    我有一个 iOS 应用程序 它在许多视图控制器中使用相同的字符串 数字等 所以我认为最好在一个文件中定义这些常量并在所有视图控制器实现中使用它 优点是更改一个数字 我只需要做一次 而不是在所有视图控制器中都使用该数字 实际上 我的 h 文件
  • iPad 照片选择器崩溃

    我正在使用以下函数根据 UIActionSheet 的结果激活设备相机或图像选择器 如果 fromCamera YES 那么它适用于 iPhone 和 iPad 如果 fromCamera NO 那么它可以在 iPhone 上运行并出现图像
  • 您是否标记 UIView 或将它们保留为属性?

    这主要是一个风格问题 但自从我开始为 iPhone 编程以来 我一直很好奇其他人的想法是什么 当您的 iPhone 应用程序中有一个 UIView 并且需要在应用程序的其他位置访问它时 通常在视图控制器中的另一个函数中 您是否喜欢用整数标记
  • 最小的 iOS 蓝牙管理器示例

    我一直在构建一个最小的示例 用于使用 iOS 5 0 中的 BluetoothManager 私有框架来检测附近的蓝牙设备 使用此问题中找到的答案 寻找触手可及的通用蓝牙设备 https stackoverflow com question
  • 使用 iOS 8 自定义键盘发送图像?

    我一直在为 iOS 8 开发自定义键盘 但在尝试使用键盘发送图像时偶然发现了一个问题 我做了一些研究 似乎没有一种简单的方法可以做到这一点UITextDocumentProxy因为只有NSStrings被允许 我是否忽略了使用自定义键盘发送
  • iPhone 应用程序中的异步、同步、线程

    我正处于一个应用程序的设计阶段 该应用程序将利用 REST Web 服务 并且在使用异步 同步和线程方面遇到了困境 这是场景 假设您有三个选项可供深入研究 每个选项都有自己的基于 REST 的资源 我可以使用同步请求延迟加载每个请求 但这会
  • 如何知道我的应用程序使用了多少 iCloud 空间?

    有没有办法查看我的应用程序正在备份到 iCloud 的内容以及它消耗了多少内存 Settings gt iCloud gt Storage Backup gt Manage Storage将显示正在备份的总计内容 iOS 会备份位于应用程序
  • 导入 RNCryptor 后架构 armv7 的未定义符号

    我导入了 RNCryptor 可以在这里找到 https github com rnapier RNCryptor https github com rnapier RNCryptor进入我的应用程序 但是 我在日志中收到了三个错误 Und
  • Javafx 拖放 TabPane

    我 在 JavaFx 应用程序中 有一个带有不同选项卡的选项卡 我想实现拖放功能以将选项卡拖到舞台之外 这样它就可以生成一个新窗口 就像在 Google Chrome 中一样 谢谢您的帮助 您应该检查 Tom Schindl 在他的网站上显
  • 在 Objective C 的类方法中引用类本身

    我希望我没有跳过 ObjC 手册中的这一部分 但是是否可以从类的一个类方法中引用该类 就像在 PHP 中一样 您将使用 this 来引用当前实例 而 self 引用实例的类 this 的 ObjC 等价物将是 self 那么 PHP 的 s
  • 如何将 ios7 通用应用程序升级到基于 Xcode 6 的通用故事板应用程序?

    我目前有一个基于 xcode 5 ios 7 的通用应用程序 因此有两个故事板 我正在考虑将其更新到 ios 8 有没有办法 最佳方法将两个故事板迁移到通用的单个故事板 我在 xcode 6 中看不到转换选项 None
  • NSArrayController 无需将大型数据集加载到数组中

    我想使用 NSArrayController 向 NSTableView 提供数据 我面临的问题是我不想将所有数据预先加载到数组中 然后使用数组控制器setContent 方法 我的数据模型是一个管理数百万条记录的大型现有代码库 它包含有效
  • 从 robovm 项目创建 iOS 静态库(JNI 中的 BAD_ACCESS)

    我有大量的Java代码 只有计算函数 没有UI 我想在iOS中将其重用为静态库 我的方法是使用robovm http www robovm com并按照robovm论坛中两篇文章中描述的非官方方式创建静态库 1 基本方式 https gro
  • Objective-C 中是否有相当于 C++ 动态转换的功能?

    如果我有两个类 子类和超类 SuperClass super new SuperClass SubClass sub new SubClass SubClass sub pointer The nice one line cast belo
  • 未知异常和崩溃

    当我尝试快速滚动表格视图或从远程重新加载数据时 我的应用程序崩溃了 当我先进行远程获取然后滚动表格视图时 一切似乎都工作正常 我不知道下面的崩溃日志意味着什么 它只是有时工作正常 有时崩溃 Incident Identifier 710A1
  • Kendo Ui 像 Windows 桌面一样可拖动

    我需要模拟桌面图标拖放 我这样做 draggable kendoDraggable container desktop hint function return draggable clone dragend function e cons
  • 使用 UITabBarController 时覆盖整个屏幕的视图?

    我想在 UITabBarController 设置中在整个屏幕上覆盖 HUD 样式的透明图形 执行此操作的按钮位于第一个选项卡的屏幕 FirstViewController 中 并且覆盖层也应该覆盖选项卡 这可能吗 您可以将新视图直接附加到
  • 具有延迟 NSMenu 的 NSButton - Objective-C/Cocoa

    我想创建一个NSButton单击时会发送一个操作 但按下 1 或 2 秒时会显示 NSMenu 和这个问题完全一样here https stackoverflow com questions 3309030 how to create ns
  • 无法将项目添加到 NSMutableArray ivar

    我的目标是将字符串添加到数组中 并在我调用的方法中执行此操作 在这个方法中 我在数组中得到一个空值 但不知道为什么 我在课程开始时有这样的内容 NSMutableArray listOfEvents 以及我在每个事件上调用的方法 void
  • 从 NSImage 获取像素和颜色

    我创建了一个 NSImage 对象 理想情况下想确定它包含多少个像素颜色 这可能吗 此代码呈现NSImage into a CGBitmapContext void updateImageData if image return Dimen

随机推荐

  • 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 山狮 的应用程序 我有一堆按钮 我想将它们拖到其他对象中 例如文本字段 我按照苹果开发网站上的教程进行操作 但我无法让拖动部分工作 放置部分工作 例如 我可以将文件从查找器拖到文