20

でポップオーバーを開くアプリケーションがありますNSTextField。テキストフィールドは編集できません。テキストフィールドの動作はに設定されていEditableます。このフィールドにテキストを貼り付けてコピーすることはできますが、編集することはできません。

誰もが知っている、何が間違っている可能性がありますか?

4

8 に答える 8

42

まだ答えが必要かどうかはわかりませんが、まだ探している人がいるかもしれません。Apple 開発者フォーラムで解決策を見つけました。原作者の引用:

主な問題は、キーボード イベントの動作方法です。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 と応答しなければならない別のウィンドウが必要な場合は、いつでもサブクラスを作成できます。

于 2011-10-17T13:17:25.030 に答える
8

バグだと気付くまで、これにもしばらく苦労しました。

ただし、NSStatusItem ビューの isActive 状態に依存する代わりに、実装した NSPopover の isShown プロパティを使用する方がはるかに信頼性が高いことがわかりました。

私のコードでは、NSViewController に NSPopover があります。

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

        return YES;
    }
于 2012-06-20T14:39:27.787 に答える
2

Balazs Toth の回答は機能しますが、ポップオーバーを NSStatusItem.view にアタッチすると、ステータス アイテムが応答しなくなります。フォーカスするには 2 回クリックする必要があります。

于 2011-11-06T22:23:00.847 に答える
1

このソリューションを使用しているときに私が見つけたのは、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をクリックすると変化する bool 値があることです。システムは自動的に「canBecomeKeyWindow」をチェックします。 NOを返し、ユーザーがそれをクリックした後 ( NO を返している間)、ブール値を変更し、システムが再度要求したときにYES を返します ( NSTextField編集のためにNSPopoverがクリックされている場合)。

補足:

  • CBStatusBarViewはNSStatusItemのカスタム ビューです
  • CBAppDelegateは私の App Delegate クラスです
于 2011-12-20T10:54:09.433 に答える
0

間違いなくバグです。そのバグ レポートはまさに私がやろうとしていたことです。ステータス アイテムの作成と mousdown のオーバーライドまでも。

Balazs Tothの答えが機能することを確認できます。途中で邪魔にならないか心配です。

于 2011-11-01T19:43:42.480 に答える
-1

バグ。http://openradar.appspot.com/9722231

于 2011-08-28T06:06:16.810 に答える