8

私のアプリにはNSOutlineViewとがありNSTableView、両方で同じ問題が発生しています。いずれかの行が選択されている状態で Tab キーを押すと、次のキー ビューをファーストレスポンダーにする代わりに、最初の列が編集モードになります。次の重要なビューに移動するには、すべての列をタブで移動する必要があります。

また、いずれかのビューに Shift キーを押しながらタブ移動すると、最後の列が編集モードになり、前のキー ビューに移動するためにさらにシフト タブが必要になります。

重要な場合は、自分のではなく、自動計算されたキー ビュー ループを にNSWindow設定して使用していautorecalculatesKeyViewLoop = YESます。ユーザーが列を編集することを選択したら、列間をタブで移動したいと思いますが、タブキーが編集モードをトリガーするのは標準的な動作ではないと思います。

アップデート

以下の役立つ回答のおかげで、解決しました。基本的に-keyDown、カスタム テーブル ビュー クラスをオーバーライドします。これは、テーブル ビューからのタブ移動とシフト タブ移動を処理します。ただし、テーブル ビューへのシフト タブ移動を解決するのはより困難でした。別のビューからコントロールを受け入れる場合YES、カスタム テーブル ビューにブール値のプロパティを設定します。-acceptsFirstResponder

デリゲート-tableView:shouldEditTableColumn:rowは、現在のイベントがシフト タブkeyDownイベントである場合にそれをチェックします。-tableView:shouldEditTableColumn:rowが呼び出され、それはシフト タブ イベントではありません。テーブル ビューのプロパティを に戻してNO、通常どおり編集できるようにします。

以下に完全なソリューションを貼り付けました。

/* CustomTableView.h */

@interface CustomTableView : NSTableView {}

@property (assign) BOOL justFocused;

@end

/* CustomTableView.m */

@implementation CustomTableView

@synthesize justFocused;

- (BOOL)acceptsFirstResponder {
    if ([[self window] firstResponder] != self) {
        justFocused = YES;
    }

    return YES;
}

- (void)keyDown:(NSEvent *)theEvent
{
    // Handle the Tab key
    if ([[theEvent characters] characterAtIndex:0] == NSTabCharacter) {
        if (([theEvent modifierFlags] & NSShiftKeyMask) != NSShiftKeyMask) {
            [[self window] selectKeyViewFollowingView:self];
        } else {
            [[self window] selectKeyViewPrecedingView:self];
        }
    }
    else {
        [super keyDown:theEvent];
    }
}

@end

/* TableViewDelegate.m */

. . .

- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn
              row:(NSInteger)row
{
    NSEvent *event = [NSApp currentEvent];
    BOOL shiftTabbedIn = ([event type] == NSKeyDown
                          && [[event characters] characterAtIndex:0] == NSBackTabCharacter);

    if (shiftTabbedIn && ((CustomTableView *)tableView).justFocused == YES) {
        return NO;
    } else {
        ((CustomTableView *)tableView).justFocused = NO;
    }

    return YES;
}

. . .
4

5 に答える 5

9

これがデフォルトの動作です。行が選択されていない場合は、テーブル ビュー全体にフォーカスがあり、Tab キーを押すと次のキー ビューに切り替わります。行が選択されている場合、テーブル ビューは編集を開始するか、既に編集している場合は次のセルに移動します。

AppKit リリース ノートから:

テーブルは、次のようにセル間ナビゲーションをサポートするようになりました。

  • テーブルに前方にタブ移動すると、テーブル全体がフォーカスされます。
  • その行にインスタンスが 1 つしかない場合、Space を押すと、選択された行の NSButtonCell で 'performClick:' が試行されます。
  • もう一度タブを押すと、最初の「フォーカス可能な」(1) セルがあれば、そのセルがフォーカスされます。
  • 新しくフォーカスされたセルが編集可能な場合、編集が開始されます。
  • Space を押すと、セルで「performClick:」が呼び出され、変更された場合は、後でデータソースの値が設定されます。(2)
  • テキストセルが編集中の場合、Enter キーを押すと編集がコミットされ、フォーカスがテーブルビューに戻ります。Tab/Shift-tab は編集をコミットしてから、新しいタブループ動作を実行します。
  • タブ移動は 1 行のみを移動します
  • 行の最後のセルに到達すると、タブは次のフォーカス可能なコントロールにフォーカスを移します。
  • テーブルにタブで戻ると、フォーカス可能な最後のセルが選択されます。

この動作を変更したい場合は、デリゲート メソッドtableView:shouldEditTableColumn:row:が役立つ場合があります。NSTableView本当に Tab キーの動作だけに影響を与えたい場合は、サブクラス化する必要があるかもしれません。

于 2011-04-08T21:50:02.213 に答える
2

私も以前これに対処しなければなりませんでした。私の解決策は、サブクラス化NSTableViewまたはNSOutlineViewオーバーライドkeyDown:して、そこでタブキーの押下をキャッチし、それらに基づいて行動することでした。

于 2011-04-08T23:08:55.180 に答える
0

なんて都合のいい!私は昨日これを自分で見ていましたが、私が取ったアプローチ、つまり処理の確認を見るのは良いことkeyDown:です.

ただし、私はあなたのアプローチに 1 つの小さな改善点があります。Shift キーを押しながらタブを押してテーブルに戻るときに編集をトリガーするメソッドがbecomeFirstResponder呼び出しであることがわかりました。したがって、NSTableView サブクラスで行ったことは次のとおりです。

  1. タブ編集動作を無効にするかどうかを制御する合成プロパティを追加
  2. キーダウン時に、タブの最初の文字を確認します ([[theEvent characters] length]死んだキーの例外を避けるためにも確認してください!)。タブ編集が無効になっている場合は、コード サンプルに従って、次/前のビューに移動します。
  3. オーバーライドbecomeFirstResponder:
    - (BOOL)becomeFirstResponder {
        if (tabEditingDisabled) {
            [自己表示];
            はいを返します。
        }
        return [super becomeFirstResponder];
    }

これにより、テーブルビューのサブクラスにすべてのコードが保持され、デリゲートがよりクリーンに保たれます:)

唯一の危険は、becomeFirstResponder; で NSTableView が他に何をするかわからないことです。壊れたことに気付かなかったけど…

于 2011-04-10T15:32:19.240 に答える
0

これは私のために働いた:

- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
  NSEvent *e = [NSApp currentEvent];
  if (e.type == NSKeyDown && e.keyCode == 48) return NO;
  return YES;
}
于 2013-01-06T19:22:13.817 に答える