即使设置了可编辑行为,也无法在 NSPopover 上编辑 NSTextField

发布于 2024-12-01 20:07:25 字数 138 浏览 4 评论 0原文

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

任何人都知道,可能出了什么问题?

I have an application, which open popover with NSTextField. The text field is not editable. Behavior for text field is set to Editable. I still can paste and copy text to this field but i can't edit it.

Anyone knows, what can be wrong?

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

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

发布评论

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

评论(8

伴梦长久 2024-12-08 20:07:25

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

主要问题是键盘事件的工作方式。尽管 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 响应“否”的窗口,您始终可以创建一个子类。

Not sure if you still need the answer, but there may be some others still looking. I found a solution on apple developer forums. Quoting the original author:

The main problem is the way keyboard events works. Although the NSTextField (and all its superviews) receives keyboard events, it doesn't make any action. That happens because the view where the popover is atached, is in a window which can't become a key window. You can't access that window in any way, at least I couldn't. So the solution is override the method canBecomeKeyWindow for every NSWindow in our application using a category.

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

That makes the popover fully resposive. If you need another window which must respond NO to canBecomeKeyWindow, you can always make a subclass.

江城子 2024-12-08 20:07:25

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

但是,我发现使用已实现的 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;
    }

I struggled with this for a while as well, until I realized it was a bug.

However, instead of relying on an isActive state of a NSStatusItem view, I find it much more reliable to use the isShown property of the NSPopover you have implemented.

In my code, I have a NSPopover in a NSViewController:

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

        return YES;
    }
黑色毁心梦 2024-12-08 20:07:25

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

Balazs Toth's answer works, but if you're attaching the popover to NSStatusItem.view the status item becomes unresponsive - requiring two clicks to focus.

时光磨忆 2024-12-08 20:07:25

我在使用此解决方案时发现,当 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 是否被单击(或处于活动状态)的是,在我自己的自定义视图中,我有一个布尔值,当用户单击 NSStatusItem 时,该值会发生变化>,系统自动检查“canBecomeKeyWindow”,当它检查时,它将返回NO,并且在用户点击它之后(当它返回NO时>)它将改变bool 值,并在系统再次询问时返回 YES(当点击 NSPopover 进行 NSTextField 编辑时)。

旁注

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

What i found when working with this solution is that when NSStatusItem becomes unresponsive, you can easily override this behavior like this

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

You will check for the class of the window, if it matches the NSStatusBarWindow we can then check somehow if the NSStatusItem is active. If it is, that means we have to return YES, because this way the NSPopover from NSStatusItem will have all keyboard events.

What I'm using for checking if the NSStatusItem was clicked (or is active) is that in my own custom view i have a bool value which changes when user clicks on the NSStatusItem, system automatically checks for "canBecomeKeyWindow" and when it does it will return NO and after user clicks on it (while it is returning the NO) it will change the bool value and return YES when system asks again (when NSPopover is being clicked for NSTextField editing).

Sidenotes:

  • CBStatusBarView is my custom view for NSStatusItem
  • CBAppDelegate is my App Delegate class
飞烟轻若梦 2024-12-08 20:07:25

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

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

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

If anyone is still looking for an answer to this, I am working in Swift.

At the time where you wish the field to allow text entry, I have used myTextField.becomeFirstReponder()

To opt out; just use myTextField.resignFirstResponder()

把人绕傻吧 2024-12-08 20:07:25

绝对是一个错误。该错误报告正是我想要做的。甚至到创建状态项和覆盖鼠标按下。

我可以确认巴拉兹·托特的答案有效。我只是想知道它是否会妨碍我的前进。

Definitely a bug. That bug report is exactly what I was trying to do. Even down to creating the status item and overriding mousdown.

I can confirm that Balazs Toth's answer works. I just wonder if it might get in the way down the road.

烈酒灼喉 2024-12-08 20:07:25

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

Application is background only = true

,并且应该

 Application is agent = true

在这件事上花费一整天。

输入图片此处描述

If someone gets it and the solution above didn't do the trick for him.
The problem in my app was in the info tab in the targets my application was set to

Application is background only = true

and shulde of been

 Application is agent = true

Spent an entire day on this thing.

enter image description here

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