【问题标题】:Not being able to edit NSTextField on NSPopover even though Editable behavior is set即使设置了可编辑行为,也无法在 NSPopover 上编辑 NSTextField
【发布时间】:2011-11-05 01:40:00
【问题描述】:

我有一个应用程序,它使用NSTextField 打开弹出框。文本字段不可编辑。文本字段的行为设置为Editable。我仍然可以将文本粘贴和复制到该字段,但我无法对其进行编辑。

谁知道,有什么问题?

【问题讨论】:

标签: cocoa nstextfield nspopover


【解决方案1】:

不确定您是否仍需要答案,但可能还有其他人仍在寻找。我在苹果开发者论坛上找到了解决方案。引用原作者:

主要问题是键盘事件的工作方式。尽管 NSTextField (及其所有超级视图)接收键盘事件,但它不执行任何操作。发生这种情况是因为附加弹出窗口的视图位于不能成为关键窗口的窗口中。你不能以任何方式访问那个窗口,至少我不能。因此解决方案是使用类别覆盖应用程序中每个 NSWindow 的 canBecomeKeyWindow 方法。

NSWindow+canBecomeKeyWindow.h
@interface NSWindow (canBecomeKeyWindow)

@end

NSWindow+canBecomeKeyWindow.m
@implementation NSWindow (canBecomeKeyWindow)

//This is to fix a bug with 10.7 where an NSPopover with a text field cannot be edited if its parent window won't become key
//The pragma statements disable the corresponding warning for overriding an already-implemented method
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (BOOL)canBecomeKeyWindow
{
    return YES;
}
#pragma clang diagnostic pop

@end

这使得弹出框完全响应。如果您需要另一个必须对 canBecomeKeyWindow 响应 NO 的窗口,您可以随时创建一个子类。

【讨论】:

  • 您能否详细说明如何执行此操作?
  • 向项目添加文件时,您可以选择添加“Objective-C 类别”。这就是他将其命名为“canBecomeKeyWindow”的原因。将他发布的内容复制粘贴到您的代码中,它应该可以工作。
  • 非常感谢!!如果可以的话,我会 +1 一千次! :)
【解决方案2】:

我也为此苦苦挣扎了一段时间,直到我意识到这是一个错误。

但是,我发现使用您已实现的 NSPopover 的 isShown 属性而不是依赖于 NSStatusItem 视图的 isActive 状态更可靠。

在我的代码中,我在 NSViewController 中有一个 NSPopover:

  - (BOOL)canBecomeKeyWindow
    {
        if([self class]==NSClassFromString(@"NSStatusBarWindow"))
        {
            NSPopover *mainPopover = [[((AppDelegate*)[NSApp delegate]) mainViewController] mainPopover];
            if(![mainPopover isShown])
                return NO;
        }

        return YES;
    }

【讨论】:

    【解决方案3】:

    Balazs Toth 的回答有效,但如果您将弹出框附加到 NSStatusItem.view,则状态项将变得无响应 - 需要单击两次才能聚焦。

    【讨论】:

    • the_snitch: 你应该在哪个视图上覆盖这个选择器?在 NSStatusItem.view (这是我编写的自定义视图)上覆盖它不起作用。选择器永远不会被触发。
    • 我也遇到了同样的问题,不知道如何解决。
    • github.com/aschuch/AXStatusItemPopup/pull/7/… 进行此更改,它将起作用。
    【解决方案4】:

    我在使用此解决方案时发现,当 NSStatusItem 变得无响应时,您可以像这样轻松地覆盖此行为

    - (BOOL)canBecomeKeyWindow {
        if([self class]==NSClassFromString(@"NSStatusBarWindow")) {
            CBStatusBarView* view = [((CBAppDelegate*)[NSApp delegate]) statusItemView];
            if(![view isActive]) return NO;
        }
        return YES;
    }
    

    您将检查窗口的类,如果它与 NSStatusBarWindow 匹配,我们可以通过某种方式检查 NSStatusItem 是否处于活动状态。如果是,则意味着我们必须返回 YES,因为这样 NSStatusItem 中的 NSPopover 将拥有所有键盘事件。

    我用来检查 NSStatusItem 是否被点击(或处于活动状态)是在我自己的自定义视图中,我有一个 bool 值,当用户点击 NSStatusItem ,系统会自动检查 "canBecomeKeyWindow" 并且当它检查时它会返回 NO 并且在用户点击它之后(当它返回 NO )它会改变 bool 值并在系统再次询问时返回 YES(当点击 NSPopover 进行 NSTextField 编辑时)。

    旁注

    • CBStatusBarView 是我对 NSStatusItem 的自定义视图
    • CBAppDelegate 是我的 App Delegate 类

    【讨论】:

    • 遇到了同样的问题,但现在可以使用此解决方法
    【解决方案5】:

    如果有人仍在寻找这个问题的答案,我正在使用 Swift。

    在您希望该字段允许文本输入时,我使用了myTextField.becomeFirstReponder()

    选择退出;只需使用myTextField.resignFirstResponder()

    【讨论】:

      【解决方案6】:

      绝对是一个错误。那个错误报告正是我想要做的。甚至可以创建状态项并覆盖 mousdown。

      我可以确认 Balazs Toth 的回答有效。我只是想知道它是否会妨碍您前进。

      【讨论】:

        【解决方案7】:

        如果有人得到它并且上面的解决方案没有为他解决问题。 我的应用程序中的问题出在targets 中的info 选项卡中,我的应用程序设置为

        Application is background only = true
        

        应该是

         Application is agent = true
        

        在这件事上花了一整天。

        【讨论】:

          【解决方案8】:

          【讨论】:

            猜你喜欢
            • 2012-09-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多